想要理解JAVA中多态思想就必须先要搞清楚什么是:重写 (overide)
对比记忆学习
方法重载(overload):发生在同一个类中,定义了若干个方法名称相同,参数列表不同的一组方法。
方法重写(overide):发生在有继承关系的类之间,子类定义了和父类除了权限不同,其他全都相同的方法,这样的一组方法称之为方法重写。
多态是建立在继承机制上的一种机制,具体点来说就是某个行为,当由不同的人去作时会产生出不同的效果。这就好比一台性能超强的Mac pro在大佬手里是一台能搞在极高分辨率下的影视后期、同时运行大量虚拟机、复杂精细的三维场景渲染、数百条音轨同步播放、高速处理极高分辨率的图片强大工具,性能好比一个小型工作站,而在咸鱼手里只是一个装逼的摆件,外加一个视频播放器。
总之多态是一种思想,是同一份源码,不同的传参/类调用会产生不同的效果。
向上转型实际就是将父类的引用指向子类对象,当成父类对象来使用。
向上转型发生在有继承关系的类之间,不一定非要是子类,也可以是子类的子类。
父类名称 父类引用 = new 子类实例();
Animal animal = new Bird();
向上转型的最大意义在于参数统一化,降低使用者的使用难度。
public class Test {
public static void main(String[] args) {
// 2.作为类的使用者,程序的使用者
// 没有向上转型,我要使用fun方法的话,我就得了解Animal以及其子类的所有对象
// 我才能知道我到底调用的是谁
fun(new Animal());
fun(new Duck());
fun(new Bird());
}
// 1.作为类的实现者
// fun方法接收AnimaL以及其子类的对象作为参数
// 假设现在没有向上转型,AnimaL有多少子类,我就得重载多少次fun方法
// 大自然AnimaL动物子类有几百万种,就有几百万种子类,fun就得写上百万次!
public static void fun(Animal animal) {}
public static void fun(Duck duck) {}
public static void fun(Bird bird) {}
}
因为子类继承了父类,所有子类都有父类的属性,为了更简介的代码编程,为什么不能用父类指代所有子类?由此向上转型就产生了。
public class Test {
public static void main(String[] args) {
// 2.作为类的使用者,程序的使用者
// 没有向上转型,我要使用fun方法的话,我就得了解Animal以及其子类的所有对象
// 我才能知道我到底调用的是谁
fun(new Animal());
fun(new Duck());
fun(new Bird());
}
// 只要是Animal及其子类,都是天然的Animal对象,都满足is a关系
// 通过Animal最顶层的父类引用,指代所有的子类对象。
public static void fun(Animal animal) {}
}
fun()中animal 局部变量的引用调用 eat 方法时,当传入不同的对象时,表现出来了不同的 eat方法的行为,就是多态性。
初学者初次接触多态时,总是纠结调用的是谁的方法,在这里很容易弄混,其实我们不用去看前半部分,看当前是通过哪个类new的对象,若该类重写了相关方法,则调用的一定是重写后的方法。千万不要被类名称搞晕,就看new的是谁,只要new的这个对象的类中覆写了同名方法,则调用的一定是覆写后的方法。
Bird 继承 Animal,Duck 继承 Bird,此时 Duck 中没有eat()方法,则会向上继承 “最近”的eat方法,也就是说会调用父类Bird的eat,而不是调用祖父类Animal的eat。
public class Animal { public void eat() { System.out.println("Animal类的eat方法"); } }
public class Duck extends Bird{ // public void eat() { // System.out.println("Duck类的eat方法"); // } }
public class Test { public static void main(String[] args) { Animal animal = new Bird(); Animal duck = new Duck(); fun(duck); } public static void fun(Animal animal) { animal.eat(); } }
权限问题:当发生重写,必须要保证子类的权限大于等父类权限才可以重写。但是 private 修饰的父类方法不可以!!!子类压根都不可以使用,不可见,都不能继承!!!
能否重写static方法?
多态的本质就是因为调用了不同的子类“对象”,这些子类对象所属的类覆写相应的方法才能表现出不同的行为static和对象无关!!!! 方法重写只发生在普通方法中。
关于重写与构造方法的一道题
public class B { public B() { fun(); } public void fun() { System.out.println("B.fun()"); } }
public class D extends B{ private int num = 10; public void fun() { System.out.println("D.fun,num = " + num); } public static void main(String[] args) { D d = new D(); } }
正确答案: D
①程序从main进入开始,实例化一个对象D,调用类D,
②但是类D继承B,所以先执行构造方法B,此时又调用fun()方法,
③子类D重写了fun()方法,执行子类D中的fun(),
④因为没有执行 private int num = 10; ,所以num 等于整型默认值 0。
图解为:
需要注意的问题,如果使用:引用名称.方法名称();
此时 引用名称 所在属的类中必须定义该方法,不然会报错,编译器会先在类中查找是否包含指定的方法。
发生向上转型的时机
方法传参(使用最多)
向下转型我们将一个子类对象经过向上转型之后,我们就只能调用其父类的方法,再无法调用子类的方法,但有时候我们可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可。子类的引用 接收 被强制转为子类类型的父类引用指向的对象,这就是向下转型。
子类名称 子类引用 = (子类名称)父类引用
Dog dog = (Dog) animal;
要发生向下转型,必须先发生向上转型。
也就是说两个毫无相关的类之间无法强转。否者会报类型转换异常
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)