Polymorphism in Java

Polymorphism is the third major feature of object-oriented after encapsulation and inheritance.

The practical significance of polymorphism:

  • Real things often have multiple forms. For example, students, students are a kind of person, and a specific student Xiao Ming is both a student and a person, that is, there are two forms;
  • As an object-oriented language, Java can also describe multiple forms of a thing. For example, the Student class inherits the Person class, and a Student object is both a Student and a Person.
  • Polymorphism is reflected in the fact that parent class variables can point to subclass objects (the prerequisite is that there must be a parent-child relationship);
  • When using the polymorphic parent class variable to call the method, the method rewritten by the subclass will be called;

Definition of polymorphism:父类类型 变量名 = new 子类类型();

Polymorphic understanding:

  • Polymorphism is the ability to have multiple different manifestations or forms of the same behavior;
  • Polymorphism is the same interface, using different instances to perform different operations;

Characteristics of members in polymorphism:

  • Polymorphic member variables, compile and run to see the left;
Person p = new Student();
System.out.println(p.num); // num 是 Person 中的值
  • Polymorphic member method: compile to the left, run to the right;
Person p = new Student();
System.out.println(p.show()) // 调用的是 Student 中重写的方法

instanceofKeyword: used to determine whether an object belongs to a certain data type, and the return type is Boolean:

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Person p = new Student();
        if (p instanceof Student) {
    
    
            System.out.println("p 是 Student 类型");
        } else {
    
    
            System.out.println("p 不是 Student 类型");
        }
    }
}
// p 是 Student 类型

Polymorphic transformation: divided into upward transformation and downward transformation

  • Upward transformation: Polymorphism itself is a process of upward transformation 父类类型 变量 = new 子类类型(). When there is no need to face the subclass type, the corresponding operation can be completed by using the functions of the parent class;
  • Downcasting: A subclass object that has been upcasted can use the forced type conversion format to convert the parent class reference type to the subclass reference type, 子类类型 变量 = (子类类型)父类类型变量. When you need to use subclass-specific functions, you can use downcasting;
public class Test {
    
    

    public static void main(String[] args) {
    
    
        Person person = new Student();
        person.eat(); // student eat
        Student student = (Student) person;
        student.study(); // student study
    }

}

class Person {
    
    
    public void eat() {
    
    
        System.out.println("people eat");
    }
}

class Student extends Person {
    
    
    @Override
    public void eat() {
    
    
        System.out.println("student eat");
    }

    public void study() {
    
    
        System.out.println("student study");
    }
}

class Teacher extends Person {
    
    
    @Override
    public void eat() {
    
    
        System.out.println("teacher eat");
    }

    public void teach() {
    
    
        System.out.println("teacher teach");
    }
}

Excuse me, what is the result of running the question?

public class Test {
    
    

    public static void main(String[] args) {
    
    
        Shape shape = new Shape();
        shape.show(); // shape
        Circle circle = new Circle();
        circle.show(); // circle
        CircularCone circularCone = new CircularCone();
        circularCone.show(); // circular cone
    }

}

class Shape {
    
    
    public void show() {
    
    
        showShape();
    }

    public void showShape() {
    
    
        System.out.println("shape");
    }
}

class Circle extends Shape {
    
    

    @Override
    public void showShape() {
    
    
        System.out.println("circle");
    }
}

class CircularCone extends Circle {
    
    
    @Override
    public void show() {
    
    
        super.show();
    }

    @Override
    public void showShape() {
    
    
        System.out.println("circular cone");
    }
}

There are two types of polymorphism:

  • Compile-time polymorphism: method overloading;
  • Runtime polymorphism: The Java runtime system will decide which method to choose to call based on the type of instance that calls the method;
    • Object-oriented three major features: encapsulation, inheritance, polymorphism. From a certain point of view, encapsulation and inheritance are almost prepared for polymorphism;
    • The definition of polymorphism: refers to allowing different objects to respond to the same message, that is, the same message can adopt different behaviors according to different sending objects (messages are function calls);
    • The technique of realizing polymorphism is called: dynamic binding (dynamic binding), which refers to judging the actual type of the referenced object during execution, and calling its corresponding method according to the actual type;

The role of polymorphism: to eliminate the coupling relationship between types.

There are three necessary conditions for the existence of polymorphism: inheritance, rewriting, and parent class references pointing to subclass objects.

Benefits of polymorphism:

  • Substitutability: Polymorphism is substitutable for existing code. For example, polymorphism works for the Shape class, but also for other Shapes, such as Circle;
  • Extensibility: Polymorphism is extensible to the code. Adding new subclasses does not affect the polymorphism, inheritance, and operation and operation of other features of existing classes. In fact, adding new subclasses is more Easy access to polymorphic functionality. For example, after realizing CircularCone (cone), it is easier to realize semi-circular cone;
  • Interface-ability: Polymorphism is achieved by superclasses providing a common interface to subclasses through method signatures, which are then perfected or overwritten by subclasses;
  • Flexibility: It embodies flexible and diverse operations in the application and provides practical efficiency;
  • Simplicity: polymorphism simplifies the process of writing and modifying application software code, especially when dealing with the operation and operation of a large number of objects, this feature is particularly prominent and important;

Demo 1:

Demo 1

In the above example, when Father's getName()method is commented out, calling father.getName()the method will cause an error. Therefore, when the parent class reference points to the subclass method, the methods existing in the parent class must be called. If the method is overridden in the subclass, then the method in the subclass will be dynamically called at runtime, which is polymorphic. Modify as follows:

public class Test {
    
    

    public static void main(String[] args) {
    
    
        Test test = new Test();
        // 注意:采用此种方式创建实例,否则静态方法中只能创建静态内部类的实例
        Test.Father father = test.new Son();
        System.out.println(father.getName()); // son
    }

    public class Father {
    
    
        private String name = "father";

        public String getName() {
    
    
            return this.name;
        }
    }

    public class Son extends Father {
    
    
        private String name = "son";

        @Override
        public String getName() {
    
    
            return this.name;
        }
    }
}

output son. Continue to look at the following example:

public class Test {
    
    

    public static void main(String[] args) {
    
    
        Test test = new Test();
        // 注意:采用此种方式创建实例,否则静态方法中只能创建静态内部类的实例
        Test.Shape shape1 = test.new Shape();
        Test.Shape shape2 = test.new Circle();
        Test.Circle circle = test.new Circle();
        Test.CircleCone circleCone = test.new CircleCone();
        shape1.show(circle); // Shape and Shape
        shape1.show(circleCone); // Shape and CircleCone
        shape2.show(circle); // Circle and Shape
        shape2.show(circleCone); // Shape and CircleCone
    }

    public class Shape {
    
    
        public void show(Shape shape) {
    
    
            System.out.println("Shape and Shape");
        }

        public void show(CircleCone circleCone) {
    
    
            System.out.println("Shape and CircleCone");
        }
    }

    public class Circle extends Shape {
    
    

        public void show(Circle circle) {
    
    
            System.out.println("Circle and Circle");
        }

        public void show(Shape shape) {
    
    
            System.out.println("Circle and Shape");
        }

    }

    public class CircleCone extends Circle {
    
    

        public void show(CircleCone circleCone) {
    
    
            System.out.println("CircleCone and CircleCone");
        }

        public void show(Circle circle) {
    
    
            System.out.println("CircleCone and Circle");
        }

    }
}

shape2.show(circle)What is printed is Circle and Shape, why not here Circle and Circle? This is because, when a superclass variable refers to a subclass object, the type of the referenced object, not the variable's type, determines whose member method is invoked. But the called method must be defined in the superclass, that is to say, the method overridden by the subclass.

First of all, "When a superclass variable refers to a subclass object, the type of the referenced object rather than the type of the variable determines whose member method to call", which means that when running, it is the class that decides shape2.show(circle)to Circlecall whose method. However, Shapethere is no method defined in its parent class show(Circle circle), so there is no such thing as "subclass coverage". Therefore, the priority of method calls is involved here.

The order of priority from high to low is: this.show(O)-> super.show(O)-> this.show((super)O)-> super.show((super)O).

shape2.show(circle), thisrefers to shape2, but Shapedid not find show(Circle circle)the method in , so ShapeI went to find it in the parent class of , because Shapethere is no parent class in , and then went to the third priority this.show((super)O), thisstill shape2, Ofor Circle, that is (super)Circle, Circlethe parent class of Shape, Shapesearch in show(Shape shape)method, Shapethere is this method in , but shape2it points to an Circleobject, and the method Circleis rewritten in show(Shape shape), so the method is finally called Circle.show(Shape shape), which is printed out Circle and Shape.

Then look at the following example:

public class Test {
    
    

    public static void main(String[] args) {
    
    
        Shape shape = new Circle();
        shape.show(); // circle
        Circle circle = new CircleCone();
        circle.show(); // circle cone
    }
}

class Shape {
    
    
    public void show() {
    
    
        show2();
    }

    public void show2() {
    
    
        System.out.println("shape");
    }
}

class Circle extends Shape {
    
    
    public void show2() {
    
    
        System.out.println("circle");
    }
}

class CircleCone extends Circle {
    
    
    public void show2() {
    
    
        System.out.println("circle cone");
    }
}

Since shape = new Circle(), when running to shape.show(), the method will be called Circle.show(), Circlewhich is not defined in the class, so Circlethe parent class Shape.show()method of will be called. Shape.show()The method will be called in the show2()method, which has been implemented by the subclass, so show2()the method of the subclass is called.

Guess you like

Origin blog.csdn.net/xingyu19911016/article/details/128734520