2021-03-09

Object-oriented-polymorphism

1. Introduction

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

In life, for example, the function of finding area, the realization of circle, rectangle, and triangle is different. The action of running, kittens, puppies and elephants, run differently. Another example is the movement of flying. Insects, birds and airplanes are different when flying. It can be seen that the same behavior can be embodied in different forms through different things. Then there will be various types of sub-categories at this time.

2. Definition

2.1 Format

父类类型 变量名 = 子类对象;

Parent type: refers to the parent type inherited by the subclass object, or the parent interface type implemented.
E.g:

class Person{
    
    
	private String name;
	private int age;
	
    Person(String name, int age){
    
    
        this.name = name;
        this.age = age;
    }
    
	public void speak(){
    
    
		System.out.println(name + "说:我今年" + age);
	}
}
class Man extends Person{
    
    
    Man(String name, int age){
    
    
        super(name,age);
    }
}
class Woman extends Person{
    
    
    Woman(String name, int age){
    
    
        super(name,age);
    }
}

2.2 Compile-time type inconsistency with runtime type

  • When compiling, look at the "parent class", you can only call the method declared by the parent class, not the method extended by the subclass;
  • At runtime, look at the "subclass", it must be the method body that performs the subclass rewriting;

3. Polymorphic applications

3.1 Polymorphism is applied to formal parameters

The parent type is used as the method parameter, and the child object is the actual parameter.
code show as below:

public class Test01 {
    
    
	public static void main(String[] args) {
    
    
		showAnimalEat(new Dog()); //形参 Animal a,实参new Dog() 
								//实参给形参赋值   Animal a = new Dog()   多态引用
		showAnimalEat(new Cat());//形参 Animal a,实参new Cat() 
								//实参给形参赋值   Animal a = new Cat()   多态引用
	}
	
	/*
	 * 设计一个方法,可以查看所有动物的吃的行为
	 * 关注的是所有动物的共同特征:eat()
	 * 所以形参,设计为父类的类型
	 * 	此时不关注子类特有的方法
	 */
	public static void showAnimalEat (Animal a){
    
    
        a.eat();
//        a.catchMouse();//错误,因为a现在编译时类型是Animal,只能看到父类中有的方法
    }

}

3.2 Application of polymorphism to arrays

The array element type is declared as the parent type, and the actual storage is the child object

public class Test02 {
    
    
	public static void main(String[] args) {
    
    
		/*
		 * 声明一个数组,可以装各种动物的对象,看它们吃东西的样子
		 */
		Animal[] arr = new Animal[2]; //此时不是new Animal的对象,而是new Animal[]的数组对象
									//在堆中开辟了长度为5的数组空间,用来装Animal或它子类对象的地址
		arr[0] = new Cat();//多态引用   左边arr[0] 是Animal类型,右边是new Cat()
							//把Cat对象,赋值给Animal类型的变量
		arr[1] = new Dog();
		
		for (int i = 0; i < arr.length; i++) {
    
    
			arr[i].eat();
//			arr[i].catchMouse();错误,因为arr[i]现在编译时类型是Animal,只能看到父类中有的方法
		}
	}
}

3.3 Application of polymorphism in the return value

The return value type of the method is declared as the type of the parent class, and the actual return value is the subclass object

public class Test03 {
    
    
	public static void main(String[] args) {
    
    
		Animal c = buy("猫咪");
		System.out.println(c.getClass());
		c.eat();
	}
	/*
	 * 设计一个方法,可以购买各种动物的对象,此时不确定是那种具体的动物
	 * 
	 * 返回值类型是父类的对象
	 * 
	 * 多态体现在   返回值类型  Animal ,实际返回的对象是子类的new Cat(),或new Dog()
	 */
	public static Animal buy(String name){
    
    
        if("猫咪".equals(name)){
    
    
            return new Cat();
        }else if("小狗".equals(name)){
    
    
            return new Dog();
        }
        return null;
    }
}

4. Upward transformation and downward transformation

First of all, which type of object an object is created when it is new will not change from beginning to end. That is, the runtime type of this object, and the essential type will not change. This is different from the conversion of basic data types.

However, when this object is assigned to variables of different types, the compile-time types of these variables are different.

class Animal {
    
      
    void eat(){
    
    
        System.out.println("~~~"); 
    } 
}  

class Cat extends Animal {
    
      
    public void eat() {
    
      
        System.out.println("吃鱼");  
    }  
    public void catchMouse() {
    
      
        System.out.println("抓老鼠");  
    }  
}  
class Dog extends Animal {
    
      
    public void eat() {
    
      
        System.out.println("吃骨头");  
    }  
    public void watchHouse() {
    
      
        System.out.println("看家");  
    }  
}

class Test{
    
    
    public static void main(String[] args){
    
    
        Cat a = new Cat();//a编译时类型是Cat
        Animal b = a;//b编译时类型是Animal
        Object c = a;//c编译时类型是Object
        
        //运行时类型
        System.out.println(a.getClass());
        System.out.println(b.getClass());
        System.out.println(c.getClass());
        //以上输出都一样,都是Cat类型
        
       	//a,b,c的编译时类型不同
    	//通过a能调用Cat中所有方法,包括从父类继承的,包括自己扩展的
    	//通过b只能调用Animal类及它的父类有的方法,不能调用Cat扩展的方法
    	//通过c只能调用Object类才有的方法
    }
}

Why type conversion?

Because of polymorphism, there must be times when subclass objects are assigned to superclass variables. At this time, type conversion will occur during compilation .

However, after using the parent class variable to receive the subclass object, we ca n't call the method that the subclass has, but the parent class does not. This is also a little trouble that polymorphism brings us. Therefore, if you want to call a method specific to a subclass, you must perform a type conversion.

  • Upcast : When the type of the variable on the left (parent class)> the type of object/variable on the right (subclass), we call it an upcast
    • At this point, when compiling according to the type of the variable on the left, you can only call the variables and methods in the parent class, not the variables and methods specific to the subclass.
    • However, at runtime, it is still the type of the object itself
    • At this time, it must be safe, and it is also done automatically
  • Downcast : When the type of the variable on the left (subclass) <the type of the object/variable on the right (the parent class), we call it a downcast
    • At this point, when compiling according to the type of the variable on the left, you can call the unique variables and methods of the subclass
    • However, at runtime, it is still the type of the object itself
    • At this time, it is not necessarily safe, you need to use (type) for forced type conversion

Not all downcasts through compilation are correct. ClassCastException may occur. For safety, you can use the isInstanceof keyword to judge

变量名/对象 instanceof 数据类型 

Guess you like

Origin blog.csdn.net/qq_37698495/article/details/114604453