JavaSE 多态

多态

class BaseClass {               //父类
    public int book = 6;
    public void base(){
        System.out.println("父类的普通方法");
    }
    public void test(){
        System.out.printn("父类被覆盖的方法");
    }
}

public class SubClass extends BaseClass {       //子类
    public String book = "我爱JAVA";

    public void test(){
        System.out.println("子类的覆盖父类的方法");
    }

    public void sub(){
        System.out.println("子类的普通方法");
    }

    public static void main(String[] args){
        BaseClass p = new SubClass;
        System.out.println(p.book);   //输出6,表明访问的是父类对象的实例变量
        p.base();   //将调用父类继承到的base()方法
        p.test();  //调用将执行子类的test()方法
        //因为p的编译时类型是BaseClass
        //BaseClass类没有提供sub()方法,所以下面的代码编译时会出现错误
        //p.sub();
    }
}

p引用变量的编译时的类型BaseClass,而运行时的类型是SubClass,当运行时调用该引用变量的方法时,其方法总是表现出子类方法的行为特性,而不是父类方法的行为特性。
与方法不同的是,对象的实例变量则不具备多态性。比如上面p.book,输出的是BaseClass类而不是SubClass类的实例变量。

所以:多态的前提
1.要有继承关系
2.要有方法重写
3.要有父类引用指向子类对象。

PS.引用变量只能调用申明该变量时所用类里所包含的方法。比如P 只能调用BaseClass类里的方法,而不能调用SubClass类的的方法。

多态的成员特点

Fu f = new zi();

在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。先在子类中找,没有再去父类。

简单总结:成员函数在多态调用时,编译看左边,运行看右边。引用变量只能调用声明变量时所用类里包含的方法。比如Fu f = new zi(); 代码定义一个变量f ,则这额f只能调用Fu类的方法。

在多态中,成员变量的特点;
无论编译和运行,都参考左边(引用型变量所属的类)


abstract class Animal{
    abstract void eat();
}

class Cat extends Animal{
    public void eat() {
        System.out.println("吃鱼");
    }
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}

class Dog extends Animal{
    public void eat() {
        System.out.println("吃骨头");
    }
    public void KanJia() {
        System.out.println("看家");
    }
}

class Pig extends Animal{
    public void eat() {
        System.out.println("饲料");
    }
    public void GongDi() {
        System.out.println("拱地");
    }
}


class DuoTaiDemo {
    public static void main(String[] args) {
        //Cat c = new Cat();
        //c.eat();

        //Dog d = new Dog();
        //d.eat();

        Cat c1 = new Cat();
        function(c1);

        function(new Dog());
        function(new Pig());
        Animal c = new Cat();   //既是猫的类型  又是动物的类型, 这就是多态在程序中的表现
        c.eat();
    }

    public static void function(Cat c){  //封装方法 ,提高代码复用性
        c.eat();
    }
    public static void function(Dog d){
        d.eat();
    }
    public static void function(Pig p){
        p.eat();
    }
}

输出;
吃鱼
吃骨头
饲料
吃鱼

1,多态的体现
父类的引用指向了自己的子类对象。
父类的引用也可以接受自己的子类对象。

优化

abstract class Animal{
    abstract void eat();
}

class Cat extends Animal{
    public void eat(){
        System.out.println("吃鱼");
    }
    public void catchMouse(){
        System.out.println("抓老鼠");
    }
}

class Dog extends Animal{
    public void eat(){
        System.out.println("吃骨头");
    }
    public void KanJia(){
        System.out.println("看家");
    }
}

class Pig extends Animal{
    public void eat(){
        System.out.println("饲料");
    }
    public void GongDi(){
        System.out.println("拱地");
    }
}


class DuoTaiDemo {
    public static void main(String[] args) {
        function(new Cat());
        function(new Dog());
        function(new Pig());
    }
    public static void functionAnimal a){ //提高了程序的扩展性,后期出现新的动物也能直接用
        a.eat();
    }

输出;
吃鱼
吃骨头
饲料

2,多态的优点
多态的出现大大的提高了程序的扩展性。

3,多态的前提
必须是类与类之间有关系,要么继承,要么实现。
通常,还有一个前提:存在覆盖

4多态的弊端
提高了扩展性,但是只能使用父类的引用访问父类中的成员。


多态-转型

class DuoTaiDemo {
    public static void main(String[] args) {
        Animal a = new Cat();   //类型提升。向上转型。 a为父类的引用
        a.eat();
        //如果想要调用猫的特有方法,如何操作?
        //强制将父类的引用。转成子类类型。
        Cat c = (Cat)a;
        c.catchMouse();


        //千万不能出现这种操作,就是将父类对象转成子类类型,不可以将动物转成猫
        //我们能转换的是父类应用指向了自己的子类对象时,还引用可以被提升,也可以被强制转换。
        //多态自始至终都是子类对象在做着变化。
        //Animal a = new Animal();
        //Cat C = (Cat)a;
    }
    public static void function(Animal a){
        a.eat();
    }

这里写图片描述

向上转型为动物

如果把一个父类实例转换成子类类型,则这个对象必须实际上是子类实例才行。(即编译时类型为父类类型,而运行时类型为子类类型)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值