多态

向上转型

对象的向上转型一定是安全的,就是:父类对象指向子类对象。但是也有弊端,一旦向上转型为父类,就无法调用子类原本特有的内容。

public class Father{
	int num = 10;
	public void method(){
		System.out.println("父子都有的方法。父亲");
	}
	public void methodFu(){
		System.out.println("父类特有的方法。");
	}
	public void show(){
		System.out.println("父类的num:"+num);
	}
}
public class Zi extends Father{
	int num = 20;
	int member = 10;
	public void method(){
		System.out.println("父子都有的方法。孩子");
	}
	public void methodZi(){
		System.out.println("子类特有的方法");
	}
	public void show(){
		System.out.println("子类的num:"+num);
	}
}

代码当中体现多态:父类引用指向子类对象:
格式:
父类名称 对象名 = new 子类名称();
接口名称 对象名 = new 子类名称();

public class Test{
	public static void main(String[] args){
		Father fu = new Zi();
		fu.method();//父子都有的方法。孩子
		fu.methodFu();//父类特有的方法
		System.out.println(fu.num);//10
		fu.show();//子类的num20
		//System.out.println(fu.member);//fu对象中不存在member,编译报错
	}
}

上面代码中体现了访问成员变量的两种方式:
1:直接通过对象名成访问成员变量,看等号左边是谁,优先用谁,没有则向上找。
2:直接通过成员方法访问成员变量,看该方法属于谁,优先用谁,没有则向上找。

而在多态的代码中,成员方法的访问规则是:
创建对象时,new  后面跟的是哪个类,就优先用谁,没有则向上找。
		口诀:编译看左边,运行看右边。

上面代码通过对象名访问成员变量,等号左边是父类,则找父类的num。
new的是Zi类对象,show()方法运行Zi类中的show。

对比:
成员变量:编译看左边,运行还看左边。
成员方法:编译看左边,运行看右边

编译看左边指的是,在编译阶段优先看等号左边,如果左边这个类中没有该方法/变量,则编译不通过,运行看左/右,指运行是,左/右类中是否含该方法/变量,有就运行,没有则向上找。

向下转型

public abstract class Animal {
      public abstract void eat();
}
public class Cat extends Animal {
    public void eat(){
        System.out.println("猫吃");
    }
    public void catchMouse(){
        System.out.println("猫子类特有方法");
    }
}
public class Dog extends Animal {
    public void eat(){
        System.out.println("狗吃");
    }
    public void watchHouse(){
        System.out.println("狗看家");
    }
}

向上转型一定是安全的,但也有弊端(一旦向上转型为父类,就无法调用子类原本特有的内容)

解决方法:用对象的向下转型
对象的向下转型,其实是一个【还原】的动作
   格式:子类名称 对象名 = (子类名称) 父类对象。

必须保证对象本来创建的时候,就是猫,才能向下转型猫。
如果对象创建的时候本来就不是猫,现在非要向下转型成为猫,就会报错。

public class DemoMain {
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.eat();
        //animal.catchMose();一旦向上转型为父类,就无法调用子类原本特有的内容。
        Cat cat = (Cat)animal;
        cat.catchMouse();//子类特有的方法
        /*Animal animal1 = new Animal() {
            @Override
            public void eat() {
                System.out.println("吃");
            }
        };
        Cat cat1 = (Cat)animal1;
        cat1.catchMouse();//报错,本来是动物,不是猫*/

        //下面是错误的乡下转型
        Dog dog = (Dog) animal;//本来new的时候是一只猫,现在被变成了狗,错误ClassCastException
    }
}

如何才能知到一个父类引用的对象,本来是什么子类
格式: 对象 instanceof 类型, 这将会得到一个boolean值结果。

public class Instanceof {
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.eat();
        //如果调用子类特有方法,需要向下转型。
        if (animal instanceof Dog){
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        if(animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
        giveMeAPet(new Dog());
    }
    public static void giveMeAPet(Animal animal){
        if (animal instanceof Dog){
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        if(animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值