多态:

面向对象的三大特征之一,描述事物的多种形态的一种语法. — 提高代码的拓展性,提高程序的扩展性,延展性,更灵活通用

多态的前提:

   1、必须要有继承/实现类关系
   2、要有方法重写
   3、父类引用指向子类对象/接口引用指向实现类对象

public class Demo {
    public static void main(String[] args) {
        //多态:父类引用指向子类对象,简单理解为:父类型接受子类型
        //Animal a:父类引用
        //new Dog():子类对象
        Animal a = new Animal();
        Dog d = new Dog();
        Object obj = new Dog();
        int b = 10;
        //隐式转换:大类型转小类型
        double c = b;
    }
}


public class Animal {
    //父类
    public void eat() {
        System.out.println("动物吃食物。");
    }
}



//子类
class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("小狗吃骨头。");
    }
}

多态的三种情况

1、普通类多态:指的父类型是一个普普通通的类。

注意:如果是普通类多态的话,方法重写为非必要条件。

2、抽象类多态:指的父类型是一个抽象类。

3、接口多态:指的就是等号的左边是一个接口类型。

public class Demo {
    public static void main(String[] args) {
        //接口引用指向实现类对象
        Swimming s =new Dog();
        s.swim(); 
    }
}


//接口
public interface Swimming {
    void swim();
}

//实现类
class Dog implements Swimming {
    @Override
    public void swim() {
        System.out.println("狗学会了仰泳");
    }
}

多态语法下成员特点

成员变量:编译看左边(父类),运行看左边(父类)。

成员方法:编译看左边(父类),运行看右边(子类)。

//父类
class Fu {
    int num = 10;

    public void method(){
        System.out.println("Fu.. method");
    }
}


//子类
class Zi extends Fu {
    int num = 20;

    public void method(){
        System.out.println("Zi.. method");
    }
}



public class Test2Polymorpic {
    /*
         多态的成员访问特点:

                成员变量: 编译看左边 (父类), 运行看左边 (父类)

                成员方法: 编译看左边 (父类), 运行看右边 (子类)
     */
    public static void main(String[] args) {
        Fu f = new Zi();
        System.out.println(f.num);
        f.method();
    }

多态的好处和弊端

好处:将方法的参数类型设计为父类型,未来调用方法时,可以传递任意对象,从而提高方法的灵活性。

弊端:由于编译看左的语法限制,导致多态语法下不能访问子类的特有成员

解决方案:多态语法的向下转型解决。

//动物抽象类
public abstract class Animal {
    public abstract void eat();
}

class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

class Pig extends Animal {
    @Override
    public void eat() {
        System.out.println("猪吃白菜");
    }
}

//饲养员类
public class Breeder {
/*    public void useDog(Dog dog) {
        dog.eat();
    }
*/
//当方法的参数是父类型,方法可以接受任意子类对象
public void useAnimal(Animal e) {
    e.eat();
}
// 当方法的返回值类型是父类时,方法中可以返回任意子类对象
 public Animal getAnimal() {
     return new Cat();
 }
}

//主类
public class Demo {
    public static void main(String[] args) {
        //创建一个饲养员对象
        Breeder breeder = new Breeder();
        //喂动物吃饭
        breeder.useAnimal(new Dog());
        breeder.useAnimal(new Cat());
        breeder.useAnimal(new Pig());

    }
}

多态的转型

向上转型:(自动类型转换)

向下转型:(强制类型转换)

注意:向下转型通常会伴随:ClassCaseException类型转换异常,为了使代码更加健壮,推荐在强转之前使用instanceOf判断一下来规避问题。

public class Demo {

    public static void main(String[] ar gs) {
        //接口引用指向实现类对象
        Swimming s = new Dog();  //向上转型:父类引用接收子类对象
        s.swim();

        //向下转型:(强制类型转换),好处:不受多态的限制。
     //s记录的对象真实类型是否是Dog类型,是的话instanceOf会返回true,否则返回false
     if(s instanceOf Dog){
        Dog dog = (Dog) s;
        dog.eat();
        dog.lookHome();
    }

  }
}

//接口
public interface Swimming {
    void swim();
}

//实现类
class Dog implements Swimming {
    @Override
    public void swim() {
        System.out.println("狗刨");
    }

    public void eat() {
        System.out.println("狗吃骨头");
    }

    public void lookHome() {
        System.out.println("狗看家");
    }

}

发表回复

您的电子邮箱地址不会被公开。