I am learning Java inheritance in VScode (characteristics of Java inheritance, super keyword, comparison between super and this, method rewriting, subclass constructor) II

Class members include: member variables; member methods; construction methods

Construction method: no matter what modifiers can be inherited
Member variables: all can be inherited, but pay attention to one point (inheritance! = call, private ones cannot be called)
member methods: non-private can. Not private.

My personal blog homepage: If '' can really escape 1️⃣ say 1️⃣ blog homepage
about Java basic grammar learning ----> you can refer to my blog: "I learn Java in VScode"
about —> you can refer to my blog This article "I learn Java inheritance in VScode (what is Java inheritance, characteristics, what does subclass inheritance) 1"

Article directory

Characteristics of member variable access in inheritance: the principle of proximity

This means that if there is a member variable with the same name as the parent class in the subclass, the subclass will preferentially access its own member variable instead of the member variable with the same name inherited from the parent class.

Specifically, when using a member variable in a subclass, the system first checks whether the subclass itself has this member variable, and if so, directly uses the member variable of the subclass. If there is no such member variable in the subclass, the system will continue to search upwards to find whether there is a member variable with the same name in the parent class. If a member variable with the same name is found in the parent class, then the member variable of the parent class will be used.

This feature ensures that in the inheritance relationship, subclasses can hide or override member variables of the parent class by defining member variables with the same name as the parent class. In this way, subclasses can personalize the member variables inherited from the parent class according to their own needs.

It should be noted that although the subclass can hide the member variables of the parent class, this will not affect the member variables of the parent class itself, and the member variables of the parent class still exist in the parent class. If you need to access the member variables of the parent class in the subclass, you can use the super keyword to refer to the member variables of the parent class.
insert image description here

super keyword

In Java, superis a keyword used to indicate a reference to a parent or superclass (base class). It can be used in subclasses to access member variables, member methods or constructors of the parent class. There are mainly the following uses:

  1. Access the member variables of the parent class: Use superkeywords to access the member variables of the parent class in the subclass, even if there is a member variable with the same name in the subclass.

  2. Call the member method of the parent class: In the subclass, use superkeywords to call the method in the parent class that is overridden by the subclass, or call the method in the parent class that is not covered by the subclass.

  3. Call the constructor of the parent class: In the constructor of the subclass, the superconstructor of the parent class can be explicitly called by using keywords to ensure that the initialization logic in the parent class is executed.

The use of superkeywords can help subclasses interact and inherit from parent classes, thereby effectively extending and reusing code.

super and this comparison

In Java, thisboth keywords and superkeywords are used to access members of a class or call a constructor, but they have different functions and usages.

关键字:
- `this`:用于引用当前类的实例,用于访问当前类的成员变量、方法和构造方法。
- `super`:用于引用当前类的父类,用于访问父类的成员变量、方法和构造方法。

1. thisKeyword:

`this` 关键字用于引用当前类的实例。可以理解为一个变量。
		表示当前对象的地址,并且用于访问或调用当前类的成员变量和方法。
实际上是通过这个方法的隐式参数来传递当前对象的引用。
		这个隐式参数就是 this,它指向当前调用该方法的对象。
  • Used to refer to the instance of the current object, that is, the object whose method or constructor is currently being invoked.
  • Can be used to disambiguate between member variables and local variables if they have the same name.
  • Can be used to call other constructors of the class to reuse code in one constructor (constructor overloading).

2. superKeywords:

`super` 关键字用于引用当前类的父类(超类)。
	它表示父类的存储空间,并且用于访问或调用父类的成员变量、方法或构造方法。
  • Used to refer to members of the parent class (super class) or to call the constructor of the parent class.
  • superThe methods and members of the superclass can be accessed through the keyword, especially when the method of the superclass is overridden in the subclass.
  • In the construction method of the subclass, you can use superthe keyword to call the construction method of the parent class to ensure that the initialization work of the parent class can be executed.

3. Example:

class Parent {
    
    
    int value = 10;

    void display() {
    
    
        System.out.println("Parent class method");
    }
}

class Child extends Parent {
    
    
    int value = 20;

    void display() {
    
    
        System.out.println("Child class method");
    }

    void printValues() {
    
    
        int value = 30;
        System.out.println(value); // Prints local variable value (30)
        System.out.println(this.value); // Prints Child class variable value (20)
        System.out.println(super.value); // Prints Parent class variable value (10)

        this.display(); // Calls Child class method
        super.display(); // Calls Parent class method
    }
}
Summarize:
  • thisKeywords are used for current object references and constructor calls.
  • superKeywords are used to access superclass members and call superclass constructors.
usage:
  • Access member variables: this.成员变量名Indicates the member variables of the current class and super.成员变量名the member variables of the parent class.
  • Access member method: this.方法名(...)means the member method of the current class, super.方法名(...)means the member method of the parent class.
  • Access constructor: this(...)Indicates the construction method of the current class and super(...)the construction method of the parent class.
1.> When the names of local variables and member variables are different, thisthe keyword can be omitted.

In Java, if the local variable in the method does not have the same name as the member variable of the class, the compiler will automatically distinguish them and use the local variable first. So, when there is no naming conflict, you can omit thisthe keyword to refer to the member variables of the class.

However, when a local variable and a member variable have the same name, in order to clearly specify that you are using a member variable of the class, you need to use the thiskeyword to distinguish them.

public class Student {
    
    
    private String name; // 成员变量

    public Student(String name) {
    
    
        // 参数name和成员变量name同名,需要使用this关键字来区分
        this.name = name;
    }

    public void displayInfo(String name) {
    
    
        // 参数name和成员变量name不同名,可以省略this关键字
        System.out.println("传入的参数name:" + name);
        System.out.println("成员变量name:" + this.name);
    }
}

In the example above,The parameters in the constructor have the same name nameas the member variables of the class name , so we use this.nameto refer to the member variables.
In the displayInfo method, the parameters nameand member variables name have different names, so we can omit this keywords and use local variables directly name.

2.> this(...) Used to call other constructors of the same class in a constructor. It can only be used inside the constructor and must be the first statement of the constructor.
 // Constructor with three parameters___具有三个参数的构造函数
    public Student(String name, int age, String school) {
    
    
        this.name = name;
        this.age = age;
        this.school = school;
    }

    // Constructor with no parameters, calling the three-parameter constructor using this(...)
    //没有参数的构造函数,使用以下(...)调用三参数构造函数
    public Student() {
    
    
        this(null, 0, "Magic_School");
    }

In Java, if there are member variables with the same name, they can be distinguished by using specific keywords. Usually there are three ways:

就近原则

1. Start from the local position and look up:

If a local variable with the same name is defined in the current scope (method or code block), it will override the member variable with the same name. In this case, to access member variables, you can use thiskeywords to clearly indicate that you want to access member variables of the current class.

public class MyClass {
    
    
    private String name = "Class member variable";

    public void printName(String name) {
    
    
        System.out.println(name);       // 局部变量name
        System.out.println(this.name);  // 类的成员变量name
    }
}

2. Search upwards from the member position of this class:

If a member variable with the same name appears in different methods of the current class, you can directly use the name of the member variable to access, and the compiler will automatically select the correct member variable.

public class MyClass {
    
    
    private String name = "Class member variable";

    public void method1() {
    
    
        System.out.println(name);  // 类的成员变量name
    }

    public void method2() {
    
    
        System.out.println(name);  // 类的成员变量name
    }
}

3. Look up from the position of the parent class member:

If the current class inherits from other classes, and there are member variables with the same name in the parent class and the child class, you can use superkeywords to access the member variables of the parent class.

public class ParentClass {
    
    
    protected String name = "Parent class member variable";
}

public class ChildClass extends ParentClass {
    
    
    private String name = "Child class member variable";

    public void printNames() {
    
    
        System.out.println(name);          // 子类的成员变量name
        System.out.println(this.name);     // 子类的成员变量name
        System.out.println(super.name);    // 父类的成员变量name
    }
}

Summary: In Java, by using thiskeywords, you can point to the member variables of the current class, and superkeywords can point to the member variables of the parent class. Using different keywords, you can access the correct member variables.

this keyword + super keyword

在Java中,如果在不同的作用域(例如实例变量和局部变量)中出现了同名的变量,
	可以使用`this`关键字来引用实例变量并访问正确的变量。`
this`关键字是对当前类实例的引用。

For example:

public class MyClass {
    
    
    private String name; // 这是实例变量

    public MyClass(String name) {
    
    
        this.name = name; // 使用"this"关键字来给实例变量赋值
    }

    public void printName() {
    
    
        String name = "局部变量"; // 这是局部变量
        System.out.println(name); // 这里引用的是局部变量
        System.out.println(this.name); // 这里引用的是实例变量
    }
}
类似地,如果一个类继承自另一个父类,并且两个类中有同名的变量,
	可以使用`super`关键字来引用父类的变量。

For example:

public class ParentClass {
    
    
    protected String name = "父类成员变量";
}

public class ChildClass extends ParentClass {
    
    
    private String name = "子类成员变量";

    public void printNames() {
    
    
        System.out.println(name); // 这里引用的是子类的变量
        System.out.println(this.name); // 这里也引用的是子类的变量
        System.out.println(super.name); // 这里引用的是父类的变量
    }
}

Summary: In Java, thiskeywords are used to refer to the current class instance, and superkeywords are used to refer to the parent class. These keywords are useful when you need to access variables with the same name but belonging to different scopes or classes.

Features of member method access in inheritance: proximity principle + super call:

In Java inheritance, member method access has two important features: the principle of proximity and the use of superkeyword calls.

1. Proximity principle:

Java中的就近原则是指在方法调用或变量访问时,会优先选择离当前位置最近的方法或变量。
	这意味着如果在当前类中存在与父类相同名称的方法或变量,Java会优先使用当前类中的方法或变量。	

The proximity principle means that in the inheritance chain, if there are member methods with the same name in the subclass and the parent class, the subclass will call its own method first, rather than the method of the parent class. In other words, the methods of the subclass "cover" (overwrite) the methods of the superclass. This feature allows subclasses to customize or modify inherited methods as needed.

class Parent {
    
    
    void print() {
    
    
        System.out.println("This is the parent's print method.");
    }
}

class Child extends Parent {
    
    
    void print() {
    
    
        System.out.println("This is the child's print method.");
    }
}

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Child child = new Child();
        child.print(); // Output: This is the child's print method.
    }
}

In the above example, the method Childin the child class printoverrides the method in the parent Parentclass print.

2. Use superthe keyword call:

通过super关键字,可以直接访问父类中的方法或变量。

Sometimes, the method of the subclass may need to call the covered method of the parent class, which can be superachieved by using keywords. superThe keyword allows a method of a superclass to be called in a subclass, even if the method is overridden by the subclass.

class Parent {
    
    
    void print() {
    
    
        System.out.println("This is the parent's print method.");
    }
}

class Child extends Parent {
    
    
    void print() {
    
    
        super.print(); // Call the parent's print method
        System.out.println("This is the child's print method.");
    }
}

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Child child = new Child();
        child.print();
        /* Output:
           This is the parent's print method.
           This is the child's print method.
        */
    }
}

In the above example, the method Childin the subclass printfirst uses the method super.print()that calls the parent class Parent, printand then performs the output of the subclass itself.

Summary:
In Java inheritance, member methods follow the principle of proximity, and methods of subclasses will call their own methods first, rather than methods of the parent class. But if you need to call the method of the parent class, you can use superkeywords to achieve it.

Code example:

class Person {
    
    
    public void eat() {
    
    
        System.out.println("Person eats rice and vegetables");
    }

    public void drink() {
    
    
        System.out.println("Person drinks water");
    }
}

class Student extends Person {
    
    
    public void lunch() {
    
    
        // 首先,检查在本类中是否有"eat"和"drink"方法,如果有,则调用本类中的方法。
        this.eat();
        this.drink();
        // 然后,直接调用父类(Person)中的"eat"和"drink"方法。
        super.eat();
        super.drink();
    }
}

// OverseasStudent类,继承自Person类
class OverseasStudent extends Person {
    
    
    public void lunch() {
    
    
        // 首先,检查在本类(OverseasStudent)中是否有"eat"和"drink"方法, 如果有,则调用本类中的方法。

        this.eat();
        this.drink();
        // 然后,直接调用父类(Person)中的"eat"和"drink"方法。

        super.eat();
        super.drink();
    }
    // 重写Person类中的"eat"方法
    @Override
    public void eat() {
    
    
        System.out.println("OverseasStudent eats spaghetti");
    }
    
    // 重写Person类中的"drink"方法
    @Override
    public void drink() {
    
    
        System.out.println("OverseasStudent drinks cold water");
    }
}

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Student localStudent = new Student();
        localStudent.lunch();

        System.out.println("--------------------");

        OverseasStudent overseasStudent = new OverseasStudent();
        overseasStudent.lunch();
    }
}

Output:

Person eats rice and vegetables
Person drinks water
Person eats rice and vegetables
Person drinks water
--------------------
OverseasStudent eats spaghetti
OverseasStudent drinks cold water
Person eats rice and vegetables
Person drinks water

Explain code:

In Java, the keyword this is used to call methods in the current class or access member variables of the current class, and the keyword super is used to call methods in the parent class or access member variables of the parent class.

In the lunch method, this.eat() and this.drink() call the eat and drink methods rewritten in the current class (OverseasStudent or Student). And super.eat() and super.drink() call the eat and drink methods in the parent class (Person).

Therefore, when OverseasStudent or Student calls the lunch method, it will first call the overridden method in the current class, and then call the method in the parent class.

In the code, the OverseasStudent class overrides the eat and drink methods in the Person class. When the OverseasStudent object calls the lunch method, it first checks whether there are eat and drink methods in the OverseasStudent class, and if so, calls the methods in the OverseasStudent class. Therefore, when the OverseasStudent object calls the lunch method, it will output "OverseasStudent eats spaghetti" and "OverseasStudent drinks cold water".

Then, the lunch method in the OverseasStudent class directly calls the eat and drink methods in the parent class Person, using the super keyword. This causes the eat and drink methods in the parent class to be called. Therefore, the OverseasStudent object will output "Person eats rice and vegetables" and "Person drinks water" after calling the lunch method.

In contrast, the localStudent object is an instance of the Student class without overriding the eat and drink methods in the Person class. Therefore, when the localStudent object calls the lunch method, it first checks whether there are eat and drink methods in the Student class, and finds that there is no, and then directly calls the eat and drink methods in the parent class Person. This explains why the output result of calling the lunch method of the localStudent object is different from that of the OverseasStudent object, but the same as the output result of the parent class Person.

Method Overriding (Method Overriding) is an important concept in object-oriented programming, which allows subclasses to redefine methods with the same name, parameter list, and return type as those in the parent class to achieve their own specific implementation. Method overriding is the key to achieving runtime polymorphism.

重写方法的核心目的是允许子类提供自己特定的实现,以便更好地适应子类的行为和需求。
	在运行时,当子类对象调用被重写的方法时,会优先执行子类中的实现,而不是父类中的实现,
这实现了运行时多态性。这意味着父类引用指向子类对象时,根据对象的实际类型来决定调用哪个方法。

1. The rewriting method name and formal parameter list must be consistent:

When the subclass needs to rewrite the method of the parent class, it must ensure that the rewritten method name and formal parameter list are exactly the same as the method of the parent class. This means that the method name and parameter types, the number of parameters, and the order of parameters in the subclass must be the same as those of the parent class method. This is to ensure that subclasses can correctly override (override) parent class methods so that the correct method is called at runtime based on the actual type of the object.

class Animal {
    
    
    public void makeSound() {
    
    
        System.out.println("Animal is making a sound");
    }
}

class Dog extends Animal {
    
    
    public void makeSound() {
    
    
        System.out.println("Dog is barking");
    }
}

In this example, the Dog class extends the Animal class and overrides the makeSound method. The method name and formal parameter list in the subclass are exactly the same as those in the parent class.

illustrate:

insert image description here

Pay attention to the problem:

为什么Animal可以new一个Dog,而Dog不可以new一个Animal()
Animal ccc = new Dog();
ccc.makeSound();
Dog eee = new Animal();
eee.makeSound();

In Java, a class can create an instance of another class as long as the class being created is a subclass of the class being created. This is because the subclass inherits the properties and methods of the parent class, so the object of the subclass can be referenced through the reference of the parent class.

在你的代码中,Dog是Animal的子类,所以可以使用Animal类的引用来创建一个Dog对象。
	这是因为Dog继承了Animal的属性和方法。
然而,Animal不是Dog的子类,所以不能使用Dog类的引用来创建一个Animal对象。
	这是因为Animal类可能没有Dog类特有的属性和方法。
所以,你可以使用Animal类的引用来创建一个Dog对象,
	但不能使用Dog类的引用来创建一个Animal对象。

A superclass reference cannot be assigned to a subclass:

insert image description here
If you want to call the fetch() method of the Dog class, you need to convert the Animal type object to the Dog type first, and then call the fetch() method. This can be achieved by using a cast((Dog)ddd).fetch();

Other code examples:
class Animal {
    
    
    public void eat() {
    
    
        System.out.println("Animal is eating.");
    }
}

class Dog extends Animal {
    
    
    @Override
    public void eat() {
    
    
        System.out.println("Dog is eating.");
    }

    public void bark() {
    
    
        System.out.println("Dog is barking.");
    }
}

public class Mains {
    
    
    public static void main(String[] args) {
    
    
        Animal animal = new Animal();
        animal.eat(); // 输出: Animal is eating.

        Dog dog = new Dog();
        dog.eat(); // 输出: Dog is eating.
        dog.bark(); // 输出: Dog is barking.

        Animal animalDog = new Dog(); // 使用父类引用指向子类对象
        animalDog.eat(); // 输出: Dog is eating.
        // animalDog.bark(); // 错误,Animal类型的引用不能访问子类特有的方法

        ((Dog) animalDog).bark(); // 使用强制类型转换调用子类特有的方法
    }
}

In Java, the reason why direct assignment of superclass (parent class) references to subclass variables is not supported involves the concepts of inheritance and polymorphism.

Inheritance in Java is one-way. Subclasses can inherit the properties and methods of the parent class, but the reverse is not true. This is because subclasses may introduce new properties and methods that parent classes do not have. If a superclass reference is directly assigned to a subclass variable, it may result in inability to access subclass-specific properties and methods, thereby violating type safety.

Polymorphism in Java is achieved by pointing to subclass objects through parent class references. This is done to allow for more flexible programming by allowing different subclass instances to be chosen dynamically at runtime. However, due to type compatibility considerations, Java does not allow direct assignment of superclass references to subclass variables.

If you want to convert a superclass reference to a subclass type, you can use Type Casting. But when performing type conversion, you need to pay attention to the real type of the object to avoid type conversion exceptions (ClassCastException) at runtime.

For example:

Superclass superClassInstance = new Subclass();
Subclass subclassInstance = (Subclass) superClassInstance; // Type Casting

Doing so requires making sure superClassInstancethat is actually Subclassan instance of , otherwise ClassCastExceptionan exception will be thrown. Therefore, be careful when doing type conversions.

When we use an example to illustrate why it is not allowed to assign a reference to a superclass (parent class) to a subclass variable in Java, suppose we have a superclass called and a subclass that inherits from Animalcalled . Both classes have a method called .AnimalDogmakeSound()

class Animal {
    
    
    public void makeSound() {
    
    
        System.out.println("一些通用的动物声音。");
    }
}

class Dog extends Animal {
    
    
    @Override
    public void makeSound() {
    
    
        System.out.println("汪汪!汪汪!");
    }

    public void fetch() {
    
    
        System.out.println("在找球玩耍。");
    }
}

Now, if we try to Dogassign an object to a Animalreference, it's ok because Dogthat's also a Animal.

Animal animal = new Dog(); // 这是有效的,因为Dog是Animal的子类

However, if we try to animalaccess the method using a reference fetch(), it will result in a compilation error, because animalreferences are Animaltypes, fetch()but Dogmethods specific to classes.

animal.fetch(); // 错误:无法为Animal类型找到fetch()方法

By not allowing this type of assignment, Java ensures that you can only access methods and properties that actually exist on the actual object type. This helps maintain type safety and avoid runtime errors.

If you need to access fetch()methods or other subclass-specific functionality, you can cast to the subclass type. However, you must ensure that the referenced object is indeed of the correct subclass type to avoid runtime exceptions.

To access methods or other functionality specific to the subclass, you can use type casting to convert the superclass reference to the subclass type. Doing so allows you to treat superclass references as subclass references at compile time, allowing you to call subclass-specific methods.

In Java, type conversion can be achieved by casting a superclass reference to a subclass type. This way, you can access subclass-specific methods.

class Animal {
    
    
    public void makeSound() {
    
    
        System.out.println("一些通用的动物声音。");
    }
}

class Dog extends Animal {
    
    
    @Override
    public void makeSound() {
    
    
        System.out.println("汪汪!汪汪!");
    }

    public void fetch() {
    
    
        System.out.println("在找球玩耍。");
    }
}

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Animal animal = new Dog(); // 创建一个Dog对象,并用Animal引用引用它

        animal.makeSound(); // 调用的是Dog类的makeSound()方法,因为它是动态绑定的

        // 使用类型转换将Animal引用转换为Dog类型
        if (animal instanceof Dog) {
    
    
            Dog dog = (Dog) animal;
            dog.fetch(); // 现在我们可以访问Dog类特有的fetch()方法
        }
    }
}

In this example, we first refer to an object with Animala reference . Then we called , which will call the method in the class , because Java supports dynamic binding (dynamic binding), and the corresponding method will be called according to the actual object type at runtime.animalDoganimal.makeSound()DogmakeSound()

Next, we use instanceofthe operator to check animalif the reference is Dogan object of type. If it is, we animaltypecast the reference to Doga type and assign it to dogthe reference. Now, we can call the method by dogreference fetch()since it is Doga method specific to the class.

It should be noted that when performing type conversion, make sure that the object pointed to by the reference is actually the target subclass type, otherwise ClassCastExceptionan exception will be thrown at runtime. Therefore, it is best to use checks before performing type conversions instanceofto ensure that type conversions are performed safely.

2. Access rights must be greater than or equal to the parent class:

When a method of a parent class is overridden in a subclass, the access modifier of the overridden method in the subclass can be larger (more permissive) than the method in the parent class, but cannot be smaller (stricter) than the method in the parent class . The order of access modifiers is: private < default (package-private) < protected < public. For example, if the parent class method is protected, then the overridden method in the child class can be protectedor public,but not default or private. This is to ensure that subclasses do not restrict access to parent class methods and ensure the correctness of the inheritance relationship.

 class Animal {
    
    
    protected void eat() {
    
    
        System.out.println("Animal is eating");
    }
}

class Dog extends Animal {
    
    
    public void eat() {
    
    
        System.out.println("Dog is eating");
    }
}

In this example, the Dog class inherits from the Animal class and changes the protected method of the parent class to a public method. The access rights of overridden methods in subclasses are greater than or equal to the access rights of parent class methods.

3. The return value type must be less than or equal to the parent class:

When a subclass overrides a parent class method, the return value type of the subclass overridden method must be a subtype (covariant) of the parent class method return value type, or be exactly the same as the parent class method return value type. This is to ensure that the method of the subclass is compatible with the method of the parent class in type, so that the object of the subclass can be used as the object of the parent class. If the return value type of the overridden method of the subclass is incompatible with the method of the parent class, it will cause a compilation error.

class Animal {
    
    
    public Animal giveBirth() {
    
    
        return new Animal();
    }
}

class Dog extends Animal {
    
    
    public Dog giveBirth() {
    
    
        return new Dog();
    }
}

In this example, the Dog class extends the Animal class and overrides the giveBirth method. The return value type in the subclass is a subclass of the return value type of the parent class method.

4. Keep method signatures consistent:

When rewriting the parent class method, it is recommended that the rewriting method of the subclass be as consistent as possible with the parent class method, including the method name, parameter list and return value type. Doing so contributes to the readability and maintainability of the code, making it easier to understand and modify. If the overridden method of the subclass is inconsistent with the method signature of the parent class method, although the compiler will not report an error, it will cause confusion and errors.

class Animal {
    
    
    public void move() {
    
    
        System.out.println("Animal is moving");
    }
}

class Dog extends Animal {
    
    
    public void move(int distance) {
    
    
        System.out.println("Dog is moving " + distance + " meters");
    }
}

In this example, the Dog class inherits from the Animal class, but the overridden method signature is inconsistent with the parent class method. Such overriding is not recommended as it can lead to confusion and errors.

Compared:

insert image description here
And with parameters:
insert image description here
In Java, Animal ccc = new Dog(); The meaning of this line of code is to create a new Dog object and assign its reference to a variable ccc of type Animal. This is a manifestation of Java's polymorphism.

In this case, ccc is a reference of type Animal, but it actually refers to a Dog object. This means that you can call all methods defined by the Animal class, as well as methods of the Animal class that the Dog class overrides.

For example, when you call ccc.move(1);, you actually call the rewritten move(int distance) method in the Dog class, not the move(int distance) method in the Animal class. This is because the Dog class overrides the move(int distance) method of the Animal class, so when you call the move(int distance) method through a reference of the Animal type, you actually call the version in the Dog class.

That's why in your code, ((Animal) ccc).move(1); actually outputs "Dog is moving 1 meters", not "Animal is moving 1 meters". Because ccc actually refers to a Dog object, it calls the move(int distance) method in the Dog class.

5. Private methods cannot be overridden:

Private methods are only accessible inside the class in which they are declared, and thus cannot be accessed, let alone overridden, in subclasses. Private methods also cannot be overridden because they are only visible inside their owning class. If the same method as the parent class private method is defined in the subclass, then a new method is actually created in the subclass instead of overriding the method of the parent class.

class Animal {
    
    
    private void eat() {
    
    
        System.out.println("Animal is eating");
    }
}

class Dog extends Animal {
    
    
    public void eat() {
    
    
        System.out.println("Dog is eating");
    }
}

insert image description here

In this example, the Dog class tries to override the parent class's private method eat, but since the private methods are only accessible inside the class in which they are declared, they cannot be accessed and overridden in the subclass.

6. Static methods cannot be overridden:

static修饰的方法可以被继承,但是不能被重写

A static method is one that is associated with a class rather than an instance, so a subclass cannot override a static method of a parent class. However, a subclass can declare a new method in its own class with the same name as the parent class static method, which is called method hiding. Method hiding is different from method overriding in that it creates a new static method in the subclass instead of overriding the static method of the parent class.

class Animal {
    
    
    public static void makeSound() {
    
    
        System.out.println("Animal is making a sound");
    }
}

class Dog extends Animal {
    
    
    public static void makeSound() {
    
    
        System.out.println("Dog is barking");
    }
}

In this example, the Dog class tries to override the static method makeSound of the parent class, but since the static method is class-related rather than instance-related, it cannot be used in the child class.

detailed:

In Java, static methods are associated with a class, not an instance of the class. When a class defines a static method, it belongs to the class itself, not an instance of the class. Therefore, static methods are called directly by the class name, not by an instance of the class.

当子类定义了一个与父类相同名称和参数列表的静态方法时,
	实际上是在子类中创建了一个新的静态方法,而不是重写父类的静态方法。
在调用静态方法时,编译器会根据引用类型来确定要调用的方法。
	所以,无论是父类引用指向子类对象,还是子类引用指向父类对象,
调用的都是引用类型所属类的静态方法,而不是实际对象的类型。

Since static methods are associated with a class, they cannot be overridden by subclasses. A subclass can define a static method with the same name and parameter list as the parent class, but in fact this creates a new static method in the subclass instead of overriding the parent class's static method.

When calling a static method by class name, the compiler determines which method to call based on the reference type. Whether the parent class reference points to the subclass object, or the subclass reference points to the parent class object, what is called is the static method of the class to which the reference type belongs, not the type of the actual object.

Therefore, since static methods are associated with a class and cannot be overridden by subclasses, static methods cannot be overridden in Java.

7. Abnormal:

The overridden method cannot throw more exceptions than the superclass method, but can throw more specific exceptions or no exceptions. This is to ensure that the overridden method of the subclass does not introduce new exceptions to be compatible with the exception handling of the parent class method. If the overridden method of the subclass throws more exceptions than the superclass method, it will cause a compilation error.

class Animal {
    
    
    public void makeSound() throws IOException {
    
    
        // code that may throw IOException
    }
}

class Dog extends Animal {
    
    
    public void makeSound() throws FileNotFoundException {
    
    
        // code that may throw FileNotFoundException
    }
}

In this example, the Dog class extends the Animal class and overrides the makeSound method. Overridden methods in subclasses can throw a more specific exception (FileNotFoundException), or throw no exception. But cannot throw more exceptions than the parent class method.

8. Using @Override:

In Java, @Overrideoverridden methods can be marked with annotations. This annotation can help the compiler check whether the rewriting conditions are met, and if not, the compiler will report an error. The use of @Overrideannotations can improve the readability and maintainability of the code, clearly indicating that the method is a method of overriding the parent class.

class Animal {
    
    
    public void move() {
    
    
        System.out.println("Animal is moving");
    }
}

class Dog extends Animal {
    
    
    @Override
    public void move() {
    
    
        System.out.println("Dog is running");
    }
}

In this example, the Dog class marks the overridden method with the @Override annotation. This can help the compiler check whether the rewriting conditions are met, and if not, the compiler will report an error. Using the @Override annotation can improve the readability and maintainability of the code, clearly indicating that the method is a method of overriding the parent class.

9. Super keyword:

In the subclass, you can use super 关键字to call the method of the parent class. By using the super keyword, subclasses can extend the functions of the parent class method while rewriting the parent class method. Subclasses can first call the method of the parent class in the overridden method, and then add their own logic. In this way, the original function of the parent class method can be preserved and extended on this basis.

class Animal {
    
    
    public void eat() {
    
    
        System.out.println("Animal is eating");
    }
}

class Dog extends Animal {
    
    
    public void eat() {
    
    
        super.eat(); // 调用父类的eat方法
        System.out.println("Dog is eating bones");
    }
}

In this example, the Dog class overrides the eat method of the parent class and calls the eat method of the parent class using the super keyword. In this way, the function of the parent class method can be extended in the subclass, the original function of the parent class method is retained, and new logic is added on this basis.
insert image description here

10. The final method:

If a method in a superclass is declared as final, then that method cannot be overridden by a subclass. A final method is a final method that cannot be modified. Its implementation is final in the parent class and cannot be modified or overridden by subclasses. This is to ensure that a method in the parent class remains unchanged in the subclass and cannot be modified.

class Animal {
    
    
    public final void eat() {
    
    
        System.out.println("Animal is eating");
    }
}

class Dog extends Animal {
    
    
    public void eat() {
    
    
        System.out.println("Dog is eating");
    }
}

In this example, the eat method in the Animal class is declared final, indicating that the method is final and cannot be overridden by subclasses. Therefore, eat in the Dog class

11. Purpose and polymorphism:

The main purpose of overriding methods is to provide subclass-specific implementation in subclasses, enabling polymorphism and inheritance features. By rewriting the method of the parent class, the subclass can implement specific functions according to its own needs without rewriting the entire method. This can improve the reusability and maintainability of the code, and also achieve polymorphism, that is, point to the subclass object through the parent class reference, and call the corresponding method according to the type of the actual object.

class Animal {
    
    
    public void makeSound() {
    
    
        System.out.println("Animal is making a sound");
    }
}

class Dog extends Animal {
    
    
    public void makeSound() {
    
    
        System.out.println("Dog is barking");
    }
}

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Animal animal = new Animal();
        Animal dog = new Dog();

        animal.makeSound(); // 输出:Animal is making a sound
        dog.makeSound(); // 输出:Dog is barking
    }
}

In this example, the Animal class and the Dog class each define a makeSound method. Polymorphism is achieved by creating objects of the Animal and Dog classes and calling their makeSound methods. At runtime, the corresponding method is called according to the actual type of the object. Even if the reference of the parent class is used to point to the object of the subclass, the method rewritten by the subclass can still be called.

The above is a detailed description of the rewriting method, each point is to ensure that the subclass correctly rewrites the method of the parent class, and realizes polymorphism and inheritance. These rules and considerations are very important in Java and need to be followed in actual programming.

class Animal {
    
    
    public void makeSound() {
    
    
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    
    
    @Override
    public void makeSound() {
    
    
        System.out.println("Dog barks");
    }
}

In this example, Dogthe class inherits from Animalthe class and overrides makeSound()the method. When the method is called makeSound(), if it is Animalan object, it will output "Animal makes a sound"; if it is Dogan object, it will output "Dog barks". This is because at runtime, Java will dynamically choose to call the method corresponding to the object type.

When using method rewriting, pay attention to following the above rules to ensure that method rewriting can correctly override the method of the parent class in the inheritance relationship, and can meet the needs of the subclass.

方法重写(Override)的本质是子类提供了与父类相同签名的方法,以实现不同的功能。
	在运行时,JVM通过虚方法表(Virtual Method Table)来确定调用哪个方法,这就是动态绑定或者后期绑定。

当我们创建一个子类对象并调用一个方法时,JVM会首先在子类的虚方法表中查找该方法。
	如果找到,就执行该方法;如果没有找到,就在父类的虚方法表中查找。这就是为什么子类可以重写父类的方法的原因。

当子类重写父类的方法时,子类的虚方法表中的对应条目会被更新为指向子类的方法,而不是父类的方法。
	这就是所谓的“覆盖虚方法表中的方法”。

Subclass constructor:

In Java, the constructor of the subclass usually calls the constructor of the parent class to ensure that all fields of the parent class are initialized correctly. This is achieved by using the super keyword. Here is an example:

public class Animal {
    
    
    private String name;

    public Animal(String name) {
    
    
        this.name = name;
    }
}

public class Dog extends Animal {
    
    
    private String breed;

    public Dog(String name, String breed) {
    
    
        super(name);  // 调用父类的构造器
        this.breed = breed;
    }
}

In this example, the Dog class is a subclass of the Animal class. The constructor of the Dog class first calls super(name) to call the constructor of the parent class Animal, and then initializes its own breed field.

In Java, you can create JavaBean with inheritance structure through inheritance.

你的要求是创建一个JavaBean,它需要满足以下条件:

1. 类名见名知意
2. 所有的成员变量都需要私有
3. 构造方法(空参和带全部参数的构造)
4. get/set方法

First, we create a base JavaBean called Person:

public class Person {
    
    
    private String name;
    private int age;

    public Person() {
    
    
    }

    public Person(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }
}

Then, we create a Student class that inherits from Person:

public class Student extends Person {
    
    
    private String school;

    public Student() {
    
    
    }

    public Student(String name, int age, String school) {
    
    
        super(name, age);
        this.school = school;
    }

    public String getSchool() {
    
    
        return school;
    }

    public void setSchool(String school) {
    
    
        this.school = school;
    }
}

In this example, the Student class inherits the properties and methods of the Person class and adds its own property school. That's how to create a JavaBean with an inheritance structure.

Guess you like

Origin blog.csdn.net/m0_74154295/article/details/132049321