第三周 Day5

1.多态的概念及条件

概念:一个事物在不同时刻体现的不同时态
    宏观角度(现实世界):
                 水:
                        液态
                        气态
                        固态
    微观角度:
        内存的变化
        
        
多态的前提条件:
    1)必须存在继承关系,没有继承关系,谈不上多态;
    2)必须存在方法重写,因为子类需要覆盖父类的功能;
    3)必须有父类引用只需向子类对象---向上转型
            格式:
                    class Fu{}
                           class Zi extends Fu{
 
                                //方法重写
                              }
                             Fu fu = new Zi() ;

2.多态的成员访问特点

 1)成员变量(非静态)
          编译看左,运行看左
 2)成员方法(非静态)
          编译看左,运行看右, 子类的方法将父类的方法覆盖了,所有使用的子类的功能
 3)静态方法算不上方法重写---跟类相关,类名.方法名()
          编译看左,运行看左
 4)构造方法访问---由于多态还是需要继承的,所以分层初始化
//父类
 class Fu{
    int num = 100 ;
    public void show(){
        System.out.println("show Fu");
    }
​
    public Fu(){
        System.out.println("Fu的无参构造方法");
    }
​
    public static void method(){
        System.out.println("method Fu");
    }
}
​
//子类
class Zi extends  Fu {
    public Zi(){
     //super();
        System.out.println("Zi的无参构造方法..");
    }
    int num = 20;
​
    public void show() {
        System.out.println("show Zi...");
    }
​
    public static void method(){
        System.out.println("method Zi");
    }
}
​
public class DuoTaiDemo {
    public static void main(String[] args){
        //父类引用指向子类对象---"向上转型的东西"
        Fu fu = new Zi() ;
        System.out.println(fu.num);//编译没有报错,说明Fu类型中有num变量,输出100
        fu.show() ;//输出show zi;
        Fu.method();//静态方法通过类名访问---非得使用对象名来访问,不建议,输出:method Fu
        Zi.method();//输出:Fu的无参构造方法 和 Zi的无参构造方法..
    }
}
​

3.多态的好处与弊端

多态的好处:
    1)提高代码的复用性(由继承保证)
    2)提高代码的扩展性(有多态保证:父类引用指向子类对象)---经常使用
//动物类
class Animal{
    public void eat(){
        System.out.println("动物都需吃");
    }
    public void sleep(){
        System.out.println("动物都需睡");
    }
}
//子类
class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
​
    public void sleep() {
        System.out.println("猫躺着睡觉");
    }
}
class Dog extends Animal {
    public void eat() {
        System.out.println("狗吃骨头");
    }
​
    public void sleep() {
        System.out.println("狗趴着睡觉");
    }
}
​
class Pig extends Animal {
    public void eat() {
        System.out.println("猪吃白菜");
    }
​
    public void sleep() {
        System.out.println("猪侧着睡觉");
    }
}
//动物工具类
class AnimalTool{
        //将构造方法私有化,目的外界类不能new
        private AnimalTool(){}
​
    //使用猫的功能
    /*public static void useCat(Cat c){//形式参数类猫---实际传递猫的对象
        c.eat();
        c.sleep();
    }
    //使用狗的功能
    public static void useDog(Dog d){
        d.eat();
        d.sleep();
    }
    public static void usePig(Pig p){
        p.eat();
        p.sleep();
    }*/
                                //父类引用指向子类对象
    public static void useAnimal(Animal a){//实际参数: Animal a = new Dog();
                                                       // Animal a = new Cat() ;
                                                         Animal a = new Pig() ;
        a.eat();    //a.eat();
        a.sleep();
    }
}
     
    
//测试类
public class DuoTaiDemo2 {
    public static void main(String[] args) {
        //多态可以提高代码的扩展性
        //之前的写法 继承版
        Cat c = new Cat() ;
        c.eat();
        c.sleep();
        Dog d = new Dog() ;
        d.eat();
        d.sleep();
System.out.println("--------------------------------------") ;
        //优化
        //提供一个静态方法,参数类型就是猫类型或者狗类型
​
        useCat(c);//实际参数就猫类对象c
        useDog(d);//实际参数就是狗类对象d
        Pig p = new Pig() ;
        usePig(p) ;
​
       // System.out.println("-------------------------------------------");
        //上面优化不好:因为当前有一个新的动物类怎么,那么需要提供静态的useXXX(XXX类型)
        //代码量大,而且上面方式:使用面向对象的思想方式
​
        //继续优化
        //定义一个类:动物工具类AnimalTool
        //定义在当前AnimalToo里面作为它的静态方法
        /*AnimalTool.useCat(c);
        AnimalTool.useDog(d);
        AnimalTool.usePig(p);*/
​
        System.out.println("======================================================");
        //继续优化:还是一样,当有新的动物类增加.又需要提供对应的useXXX(XXX类型)方法
        //使用多态的第三个前提条件:父类引用指向子类对象
   AnimalTool.useAnimal(new Cat());
        AnimalTool.useAnimal(c);
        AnimalTool.useAnimal(d);
        AnimalTool.useAnimal(new Dog());
        AnimalTool.useAnimal(p);
        AnimalTool.useAnimal(new Pig());
​
    }
    //使用猫的功能
    public static void useCat(Cat c){//形式参数类猫---实际传递猫的对象
        c.eat();
        c.sleep();
    }
    //使用狗的功能
    public static void useDog(Dog d){
        d.eat();
        d.sleep();
    }
    public static void usePig(Pig p){
        p.eat();
        p.sleep();
}
​
​
}
​
多态的弊端:
        不能访问子类的特有功能
        
解决方法:
        1)创建具体的子类对象----在堆内存中new,消耗内存空间,不建议               
          子类new子类对象
        2)将父类的引用强转转换为子类的引用 :强转类型转换的格式
            Zi z = (Zi)f ;
        子类型 变量名 = (子类型)父的引用;-------向下转型:前提:必须存在向上转型
      
//父类
class Father{
    public void teach(){
        System.out.println("教书育人!");
    }
}
//子类
class Son extends Father{
    public void teach(){
        System.out.println("教徒弟怎么上分");
    }
​
    //特有功能
    public void playGame(){
        System.out.println("会玩lol");
    }
}
//测试类
public class DuoTaiDemo3 {
    public static void main(String[] args) {
        //多态去测试
        //父类引用指向子类对象
        Father father = new Son() ;//多态
        father.teach() ;//编译看左,运行看右,存在 重写
       // father.playGame() ;//playGame()子类的特有功能
        System.out.println("-------------------------------------") ;
        //方式1
        Son son = new Son()  ;//不太好:在堆内存中new,消耗内存空间
        son.playGame();
        System.out.println("----------------------------------------");
        //向下转型:前提:必须存在向上转型,它不需要重写去new
        Son s = (Son) father;
        s.playGame();
​
        System.out.println("-------------------------------------");
        if( father instanceof Son){ //instanceof :判断前面的这个对象是否为后面类型的实例
            System.out.println("内存中就是的son的对象");
        }else{
            System.out.println("不是");
        }
​
    }
}
​

4.向下转型异常

向下转型使用不当,会出现运行时期异常--- ClassCastException:类转换异常
​
解决方案: 改动代码---因为考虑内存中和当前接收的引用类型不匹配! 看内存的变化
上一篇:2022-1-5队列/栈day5


下一篇:《Linux就该这么学》笔记#Day5