JavaSE笔记12 多态

JavaSE笔记12 多态

一.多态的概述:

面向对象的三大特征:封装,继承,多态
多态作为三大特征之一,指的是在不同的时刻,所表现出的不同的状态

举例: Cat c=new Cat();
Animal a=new Cat();
猫可以是猫的类型,即:猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物,即:动物 d = new 猫();

即:使用父类的引用去接受子类的对象

二.多态的产生条件:

多态的产生条件共有三条:

  • 要有继承关系
  • 要有方法重写,其实没有也是可以的,但是如果没有这个就没有意义
  • 要有父类引用指向子类对象,即:父 f = new 子();

代码演示:

public class Test {
    public static void main(String[] args) {
        //多态的语法:父类引用指向子类对象
        Animal animal = new Cat();
        animal.eat();
        animal.sleep();
        System.out.println("============");
        animal = new Dog();
        animal.eat();
        animal.sleep();
    }
}
//父类:将子类中共有的的成员进行抽取
class Animal{
    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
}

//子类:猫类
class Cat extends Animal{
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
    //对父类中的方法进行重写
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    @Override
    public void sleep() {
        System.out.println("猫喜欢躺在温暖的地方睡觉");
    }
}

//子类:狗类
class  Dog extends Animal{
    public void lookDoor(){
        System.out.println("狗看门");
    }

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

    @Override
    public void sleep() {
        System.out.println("狗喜欢晚睡");
    }
}

在这里插入图片描述

三.多态的成员访问特点:

多态中的成员访问特点:

  • 成员变量: 编译看左边,运行看左边
  • 构造方法: 创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化
  • 成员方法: 编译看左边,运行看右边
  • 静态方法: 编译看左边,运行看左边 (静态和类相关,算不上重写,所以,访问还是左边的)

代码演示:

public class MyTest {
    public static void main(String[] args) {
        //之前的方式
       /* Cat cat = new Cat();
        cat.sleep();
        cat.eat();
        cat.catchMouse();*/
        //多态的方式
        Animal an = new Cat();
        //多态要有方法重写,从语法层面来说你不重写,语法不报错,但是多态就没有意义了。
        an.eat(); //子类重写了父类的方法,多态的形式去调用,以子类重写过后的为准
        //多态形式调用成员方法:编译看左边,运行看右边 Animal an = new Cat();
        //即左边没有的成员方法不能调用,调用会报错,运行时看子类中的重写结果

        //多态形式访问成员变量:编译看左边,运行也看左边,实际上成员变量访问的都是父类
        int num = an.num;
        System.out.println(num);

        //多态形式创建对象,还是先初始父类数据,再初始化自己
        Animal.show();
        Cat.show();

    }
}

class Animal {
    String name;
    int age;
    int num = 20;

    public Animal() {
        System.out.println("父类的构造方法执行了");
    }

    public void eat() {
        System.out.println("吃饭");
    }

    public void sleep() {
        System.out.println("睡觉");
    }

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

class Cat extends Animal {
    int num = 100;

    public Cat() {
        System.out.println("cat的构造方法执行了");
    }

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

    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }


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

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

在这里插入图片描述

四.多态的意义:

多态最大的意义在于:对应继承提高了代码的维护性,多态则提高了代码的扩展性
对于多态的扩展性的代码演示:

package DuoTaiDemo;

public class TestDuoTai {
    public static void main(String[] args) {
        Animal an = new Cat();
        an.eat();
        System.out.println("-----------test Duo Tai--------------");
        Animal animal = new Cat();
        System.out.println(animal.num);
        Animal.show();
        Cat.show();
        System.out.println("------------test Xiang Xia-------------");
        Cat cat = (Cat) an;
        System.out.println(cat.num);
        cat.eat();
        cat.CatchMouse();
        System.out.println("------------Duo Tai Apply--------------");
        Cat ex1 = new Cat();
        MyutilsTestEat.TestEat(ex1);
        Dog ex2 = new Dog();
        MyutilsTestEat.TestEat(ex2);
        MyutilsTestEat.TestEat(new Animal());
    }
}
class Animal{
    String name;
    int age;
    int num=200;

    public Animal(){
        System.out.println("父类空参构造");
    }
    public void eat(){
        System.out.print("爱吃");
    }
    public static void show(){
        System.out.println("Father show");
    }
}
class Cat extends Animal{
    int num=20;
    public Cat(){
        System.out.println("Cat类空参构造");
    }
    @Override
    public void eat() {
        super.eat();
        System.out.println("鱼");
    }
    public void CatchMouse(){
        System.out.println("抓老鼠");
    }
    public static void show(){
        System.out.println("Son show");
    }
}
class Dog extends Animal{
    int num=2;
    public Dog(){
        System.out.println("Dog类空参构造");
    }
    @Override
    public void eat() {
        super.eat();
        System.out.println("骨头");
    }
    public void lookDoor(){
        System.out.println("看门");
    }
    public static void show(){
        System.out.println("Son Dog Show");
    }
}
class MyutilsTestEat{
    private MyutilsTestEat(){}
    //Animal an = Cat cat
    //Animal an = Dog dog
    public static void TestEat(Animal an){
        an.eat();
    }
    public static void TestEat(Cat cat){
        cat.eat();
    }
    public static void TestEat(Dog dog){
        dog.eat();
    }
}

在这里插入图片描述

五.多态的弊端以及向下转型:

多态的存在提高了代码的复用性与维护性,以及提高代码的可扩展性。但多态也存在着弊端,不能访问子类中特有的功能。想要进行访问子类中特有的功能,需要进项向下转型
代码演示向下转型:

public class MyTest {
    public static void main(String[] args) {
       /* Animal an = new Cat();  //多态就是向上转型。
        an.eat();
        System.out.println(an.num);//
        //多态的形式,不能直接调用子类特有的功能
        //an.catchMouse();
        //如果你要调用子类特有的方法,你可以向下转型,你可以把父类引用,转换成子类对象
        Cat cat = (Cat) an; //向下转型。
        System.out.println(cat.num);
        cat.catchMouse();
*/
        System.out.println("====================================");
        Animal an = new Cat();

        an.eat();
        //向下转型
        Cat cat = (Cat) an;
        cat.catchMouse();
        //类型转换异常。ClassCastException
        // org.westos.demo5.Cat cannot be cast to org.westos.demo5.Dog
        an = new Dog();
        Dog dog = (Dog) an;
        dog.lookDoor();
    }
}

class Animal {
    int num = 20;

    public void eat() {
        System.out.println("吃饭");
    }
}

class Cat extends Animal {
    int num = 500;
    int age = 2;

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

    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}

class Dog extends Animal {
    int num = 900;
    int age = 800;

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

    public void lookDoor() {
        System.out.println("狗看门");
    }
}

在这里插入图片描述

六.多态练习题:

题设1: 孔子装爹:
孔子爹是一名java讲师,有天张三请孔子爹去自己家讲java,家中只有孔子一人,过一会李四也去孔子爹他家了,孔子一看来生意了,不想失去赚钱的机会,于是乔装打扮成他爹,去教了论语,完事之后孔子又做回自己打游戏去了
题目分析:
使用多态中的知识进行解决,首先出现继承关系:即孔子继承孔子爹,并且设定两类的成员变量,如父子年龄,还有父亲特有的教java,在孔子类中需重写为教论语,并且对于孔子还有一个特有方法就是打游戏,所以需要向下转型来让孔子在教完之后做回自己
源代码:

/*
    题目:孔子装爹:
    孔子爹是一名java讲师,有天张三请孔子爹去自己家讲java,家中只有孔子一人,过一会李四也去孔子爹他家了,孔子
    一看来生意了,不想失去赚钱的机会,于是乔装打扮成他爹,去教了论语,完事之后孔子又做回自己打游戏去了
 */
public class DuoTaiPractice {
    public static void main(String[] args) {
        //演绎故事
        //装爹用多态
        KongziFather kzf = new Kongzi();
        System.out.println("孔子装爹,"+kzf.age+"岁");
        kzf.teach();
        //做回自己,向下转型
        Kongzi kong = (Kongzi) kzf;
        System.out.println("做回孔子,"+kong.age+"岁");
        kong.playGame();
    }
}
class KongziFather{
    int age = 50;

    public void teach() {
        System.out.println("讲授java");
    }
}
class Kongzi extends KongziFather{
    int age = 20;

    @Override
    public void teach() {
        System.out.println("讲授《论语》");
    }
    public void playGame(){
        System.out.println("爱玩游戏");
    }
}

运行截图:
在这里插入图片描述


题设2: 看下面程序是否有问题,如果没有,说出结果:

class A {
		public void show() {
			show2();
		}
		public void show2() {
			System.out.println("我");
		}
	}
class B extends A {
		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(); //输出1
			
			B b = new C();
			b.show(); //输出2
		}
	}

解答:
该程序首先没有错,在执行主方法时,a.show()调的方法实际上在编译时是看A中有没有show方法,显然A中有,并且方法体是show2,这时候运行时调用的是B中的show2方法,所以输出1是:爱
对于第二个输出,还是编译的时候看b中没有会向上找,在类A中找到了,所以编译会通过,执行时实际上执行的是C类中的show2方法,所以输出2是:你

七.关于多态的总结:

  • 多态:一种事物,在不同的时刻所表现出的不同状态
  • 多态的前提要有继承关系,语法想表现形式为:父类引用指向子类对象
  • 多态的好处:提高代码的复用性与维护性,同时主要提高代码的扩展性
  • 多态的弊端:不能直接调用子类特有的功能,想要访问子类特有功能,可以进行向下转型的操作

多态访问成员的特点:

  • 访问成员变量,编译看左边(父类),运行看左边(父类)
  • 访问成员方法,子类重写父类中的方法,编译看左边(父类),运行看右边(子类)
  • 访问静态方法,静态方法不参与方法重写,编译看左边(父类),运行看左边(父类)

多态的内存图演示:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值