09-02 java 多态

Posted 白杨-M

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了09-02 java 多态相关的知识,希望对你有一定的参考价值。

多态的前提、多态的特点

/*
    多态:同一个对象(事物),在不同时刻体现出来的不同状态。
    举例:
        猫是猫,猫是动物。
        水(液体,固体,气态)。
        
    多态的前提:
        A:要有继承关系。
        B:要有方法重写。
            其实没有也是可以的,但是如果没有这个就没有意义。
                动物 d = new 猫();
                d.show();
                动物 d = new 狗();
                d.show();
        C:要有父类引用指向子类对象。
            父 f =  new 子();
            
    用代码体现一下多态。
    
    多态中的成员访问特点:
        A:成员变量
            编译看左边,运行看左边。
        B:构造方法
            创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
        C:成员方法
            编译看左边,运行看右边。
        D:静态方法
            编译看左边,运行看左边。
            (静态和类相关,算不上重写,所以,访问还是左边的)
            
        由于成员方法存在方法重写,所以它运行看右边。
*/
class Fu {
    public int num = 100;

    public void show() {
        System.out.println("show Fu");
    }
    
    public static void function() {
        System.out.println("function Fu");
    }
}

class Zi extends Fu {
    public int num = 1000;
    public int num2 = 200;

    public void show() {
        System.out.println("show Zi");
    }
    
    public void method() {
        System.out.println("method zi");
    }
    
    public static void function() {
        System.out.println("function Zi");
    }
}

class DuoTaiDemo {
    public static void main(String[] args) {
        //要有父类引用指向子类对象。
        //父 f =  new 子();
        Fu f = new Zi();
        System.out.println(f.num);
        //找不到符号
        // System.out.println(f.num2);
        
        f.show();
        //找不到符号
        // f.method();
        f.function();
    }
}

多态的好处:

/*
    多态的好处:
        A:提高了代码的维护性(继承保证)
        B:提高了代码的扩展性(由多态保证)
        
    猫狗案例代码
*/

//父类,动物类
class Animal { public void eat(){ System.out.println("eat"); } public void sleep(){ System.out.println("sleep"); } } class Dog extends 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 Pig extends Animal { public void eat() { System.out.println("猪吃白菜"); } public void sleep() { System.out.println("猪侧着睡"); } } //针对动物操作的工具类 class AnimalTool { private AnimalTool(){} //不管是什么对象,都是Animal类,这就叫多态拓展性 public static void useAnimal(Animal a) { a.eat(); a.sleep(); } } class test { public static void main(String[] args) { //我喜欢猫,就养了一只 Cat c = new Cat(); //我很喜欢猫,所以,又养了一只 Cat c2 = new Cat(); //我特别喜欢猫,又养了一只 Cat c3 = new Cat(); AnimalTool.useAnimal(c); AnimalTool.useAnimal(c2); AnimalTool.useAnimal(c3); System.out.println("--------------"); //我喜欢狗 Dog d = new Dog(); Dog d2 = new Dog(); Dog d3 = new Dog(); AnimalTool.useAnimal(d); AnimalTool.useAnimal(d2); AnimalTool.useAnimal(d3); System.out.println("--------------"); //我喜欢宠物猪 //定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用 Pig p = new Pig(); Pig p2 = new Pig(); Pig p3 = new Pig(); AnimalTool.useAnimal(p); AnimalTool.useAnimal(p2); AnimalTool.useAnimal(p3); System.out.println("--------------"); } }

多态的弊端

/*
    多态的弊端:
        不能使用子类的特有功能。
*/
class Fu {
    public void show() {
        System.out.println("show fu");
    }
}

class Zi extends Fu {
    public void show() {
        System.out.println("show zi");
    }
    
    public void method() {
        System.out.println("method zi");
    }

}

class DuoTaiDemo3 {
    public static void main(String[] args) {
        //测试
        Fu f = new Zi();
        f.show();
        f.method();//编译看左边,但是左边的Fu没有method方法,会报错。不能使用子类的method方法
    }
}

多态弊端的解决;

/*
    多态的弊端:
        不能使用子类的特有功能。
        
    我就想使用子类的特有功能?行不行?
        行。
        
    怎么用呢?
        A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
        B:把父类的引用强制转换为子类的引用。(向下转型)
        
    对象间的转型问题:
        向上转型:
            Fu f = new Zi();
        向下转型:
            Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。
*/
class Fu {
    public void show() {
        System.out.println("show fu");
    }
}

class Zi extends Fu {
    public void show() {
        System.out.println("show zi");
    }
    
    public void method() {
        System.out.println("method zi");
    }

}

class DuoTaiDemo4 {
    public static void main(String[] args) {
        //测试
        Fu f = new Zi();
        f.show();
        //f.method();
        
        //创建子类对象
        //Zi z = new Zi();
        //z.show();
        //z.method();
        
        //你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?
        //如果可以,但是如下
        Zi z = (Zi)f;
        z.show();
        z.method();
    }
}

多态问题的理解:

多态的问题理解:
    class 孔子爹 {
        public int age = 40;
        
        public void teach() {
            System.out.println("讲解JavaSE");
        }
    }
    
    class 孔子 extends 孔子爹 {
        public int age = 20;
        
        public void teach() {
            System.out.println("讲解论语");
        }
        
        public void playGame() {
            System.out.println("英雄联盟");
        }
    }
    
    //Java特别火,很多人来请孔子爹去讲课,这一天孔子爹被请走了
    //但是还有人来请,就剩孔子在家,价格还挺高。孔子一想,我是不是可以考虑去呢?
    //然后就穿上爹的衣服,带上爹的眼睛,粘上爹的胡子。就开始装爹
    //向上转型
    孔子爹 k爹 = new 孔子();
    //到人家那里去了
    System.out.println(k爹.age); //40
    k爹.teach(); //讲解论语
    //k爹.playGame(); //这是儿子才能做的
    
    
    //讲完了,下班回家了
    //脱下爹的装备,换上自己的装备
    //向下转型
    孔子 k = (孔子) k爹; 
    System.out.println(k.age); //20
    k.teach(); //讲解论语
    k.playGame(); //英雄联盟

多态继承中的内存讲解:

 

 多态中的对象变化内存图解:

多态中类转换异常:

/*
    ClassCastException:类型转换异常
    一般在多态的向下转型中容易出现
*/
class Animal {
    public void eat(){}
}

class Dog extends Animal {
    public void eat() {}
    
    public void lookDoor() {
    
    }
}

class Cat extends Animal {
    public void eat() {
    
    }
    
    public void playGame() {
        
    }
}

class DuoTaiDemo5 {
    public static void main(String[] args) {
        //内存中的是狗
        Animal a = new Dog();
        Dog d = (Dog)a;
        
        //内存中是猫
        a = new Cat();
        Cat c = (Cat)a;
        
        //内存中是猫
        Dog dd = (Dog)a; //ClassCastException
    }
}
猫狗案例
/*
    多态练习:猫狗案例
*/
class Animal {
    public void eat(){
        System.out.println("吃饭");
    }
}

class Dog extends Animal {
    public void eat() {
        System.out.println("狗吃肉");
    }
    
    public void lookDoor() {
        System.out.println("狗看门");
    }
}

class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
    
    public void playGame() {
        System.out.println("猫捉迷藏");
    }
}

class DuoTaiTest {
    public static void main(String[] args) {
        //定义为狗
        Animal a = new Dog();
        a.eat();
        System.out.println("--------------");
        //还原成狗
        Dog d = (Dog)a;
        d.eat();
        d.lookDoor();
        System.out.println("--------------");
        //变成猫
        a = new Cat();
        a.eat();
        System.out.println("--------------");
        //还原成猫
        Cat c = (Cat)a;
        c.eat();
        c.playGame();
        System.out.println("--------------");
        
        //演示错误的内容
        //Dog dd = new Animal();
        //Dog ddd = new Cat();
        
        //ClassCastException
        //Dog dd = (Dog)a;//这个编译不报错,运行才报错
    }
}    
不同地方饮食文化不同的案例
/*
    不同地方饮食文化不同的案例
*/
class Person {
    public void eat() {
        System.out.println("吃饭");
    }
}

class SouthPerson extends Person {
    public void eat() {
        System.out.println("炒菜,吃米饭");
    }
    
    public void jingShang() {
        System.out.println("经商");
    }
}

class NorthPerson extends Person {
    public void eat() {
        System.out.println("炖菜,吃馒头");
    }
    
    public void yanJiu() {
        System.out.println("研究");
    }
}

class DuoTaiTest2 {
    public static void main(String[] args) {
        //测试
        //南方人
        Person p = new SouthPerson();
        p.eat();
        System.out.println("-------------");
        SouthPerson sp = (SouthPerson)p;
        sp.eat();
        sp.jingShang();
        System.out.println("-------------");
        
        //北方人
        p = new NorthPerson();
        p.eat();
        System.out.println("-------------");
        NorthPerson np = (NorthPerson)p;
        np.eat();
        np.yanJiu();
    }
}

看程序,出结果:

/*
    看程序写结果:先判断有没有问题,如果没有,写出结果
    
    多态的成员访问特点:
        方法:编译看左边,运行看右边。
        
    继承的时候:
        子类中有和父类中一样的方法,叫重写。
        子类中没有父亲中出现过的方法,方法就被继承过来了。
*/
class A {
    public void show() {
        show2();
    }
    public void show2() {
        System.out.println("我");
    }
}
class B extends A {
    /*
    public void show() {
        show2();
    }
    */

    public void show2() {
        System.out.println("爱");
    }
}
class C extends B {
    public void show() {
        super.show();
    }
    public void show2() {
        System.out.println("你");
    }
}
public class DuoTaiTest4 {
    public static void main(String[] args) {
        A a = new B();
        a.show();
        
        B b = new C();
        b.show();
    }
}

 

以上是关于09-02 java 多态的主要内容,如果未能解决你的问题,请参考以下文章

java中封装,继承,多态,接口学习总结

每个人单核苷酸多态性(SNP)形成的原因是啥?

多态性和动态铸造

Java多态——代码复用性

Java 多态

java多态/重载方法——一个疑难代码引发的讨论