面向对象的多态性

多态性的理解

可以理解为一个事物的多种形态,同一个事件发生在不同的对象上会产生不同的结果。

多态性是什么

对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)

​ 可以直接应用在抽象类和接口上

例:

class Person {
    String name;
    int age;
    int id = 1001;
    
    public void eat(){
        System.out.println("人:吃饭");
    }
    
    public void walk(){
        System.out.println("人:走路");
    }
    
}

class Man extends Person{
    
    boolean isSmoking;    
    int id = 1002;
    
    public void earnMoney(){
        System.out.println("男人负责挣钱养家");
    }
    
    public void eat(){
        System.out.println("男人多吃肉,长肌肉");
    }
    
    public void walk(){
        System.out.println("男人霸气的走路");
    }

}

class Woman extends Person{
    
    boolean isBeauty;
    
    public void goShopping(){
        System.out.println("女人喜欢购物");
    }
    
    public void eat(){
        System.out.println("女人少吃,为了减肥");
    }
    
    public void walk(){
        System.out.println("女人窈窕的走路");
    }
}

多态的优点

    1. 消除类型之间的耦合关系
    1. 可替换性
    1. 可扩充性
    1. 接口性
    1. 灵活性
    1. 简化性

虚拟方法调用

多态的使用实际上是虚拟方法调用

  • 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
  • 总结:编译,看左边;运行,看右边。
  • 对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;
  • 而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。

多态性的使用前提

  • 类的继承关系
  • 方法的重写

多态性使用的注意点

对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)

向上转型,向下转型

  • 向上转型 : 通过子类对象(小范围)实例化父类对象(大范围),这种属于自动转换
  • 向下转型 : 通过父类对象(大范围)实例化子类对象(小范围),这种属于强制转换

向上转型(实际上就是多态性)

class A {
         public void print() {
                  System.out.println("A:print");
         }
}

class B extends A {
         public void print() {        
                  System.out.println("B:print");
         }
}

public class Test{
         public static void main(String args[])
         {
                  A a = new B();          //通过子类去实例化父类
                  a.print();
         }
}

向下转型(调用子类特有的属性和方法)

class A {
         public void print() {
                  System.out.println("A:print");
         }
}

class B extends A {
         public void print() {        
                  System.out.println("B:print");
         }
         public void funcB(){
                  System.out.println("funcB");
         }
}

class C extends A {
         public void print() {        
                  System.out.println("C:print");
         }
         public void funcC(){
                  System.out.println("funcC");
         }
}

public class Test{
         public static void func(A a)
         {
                  a.print();
                  if(a instanceof B)
                  {
                          B b = (B)a;   //向下转型,通过父类实例化子类
                          b.funcB();    //调用B类独有的方法
                  }
                  else if(a instanceof C)
                  {
                          C c = (C)a;  //向下转型,通过父类实例化子类
                          c.funcC();   //调用C类独有的方法
                  }
         }

         public static void main(String args[])
         {
                  func(new A());   
                  func(new B());
                  func(new C());
         }
}

instanceof关键字

  • 使用强转时,可能出现ClassCastException的异常。
  • 为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。

instanceof的使用

  • a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
  • 如果 a instanceof A返回true,则 a instanceof B也返回true.其中,类B是类A的父类。
  • 要求a所属的类与类A必须是子类和父类的关系,否则编译错误。

java-instanceof

对象类型转换举例

public class Test {
    public void method(Person e) { // 设Person类中没有getschool() 方法
        // System.out.pritnln(e.getschool()); //非法,编译时错误
        if (e instanceof Student) {
            Student me = (Student) e; // 将e强制转换为Student类型
            System.out.pritnln(me.getschool());
        }
    }
    public static void main(String[] args){
        Test t = new Test();
        Student m = new Student();
        t.method(m);
    }
}

扩展:如何证明多态性

import java.util.Random;

class Animal  {
 
    protected void eat() {
        System.out.println("animal eat food");
    }
}

class Cat  extends Animal  {
 
    protected void eat() {
        System.out.println("cat eat fish");
    }
}

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

    }

}

class Sheep  extends Animal  {
 

    public void eat() {
        System.out.println("Sheep eat grass");

    }

 
}

public class InterviewTest {

    public static Animal  getInstance(int key) {
        switch (key) {
        case 0:
            return new Cat ();
        case 1:
            return new Dog ();
        default:
            return new Sheep ();
        }

    }

    public static void main(String[] args) {
        int key = new Random().nextInt(3);

        System.out.println(key);

        Animal  animal = getInstance(key);
        
        animal.eat();
         
    }

}
最后修改:2021 年 08 月 15 日 08 : 11 PM
如果觉得我的文章对你有用,请随意赞赏