一条咸鱼浅讲多态
这里是一条咸鱼的讲解,下面讲述不对之处请谅解。
在给同学讲多态的时候,讲了挺久,最后是通过一个面试题(如何正确用代码表达多态)讲清楚的,所以本咸鱼觉得可以记录下来让别的苦恼的同学看能不能有所收获。
刚学多态的时候老师总会讲:父类引用指向子类对象就是多态。这句话是个总结,在学多态前其实还应该知道多态的必备条件(先死记):
- 类与类(或接口与类、接口与接口)之间存在继承关系。
- 可以进行重写。
- 父类引用指向子类对象。(虽然这句是总结,但其实也可以算是多态的一个条件)
/* 有两个类,A和B,A是B的父类 */ //我们学多态前(不是多态) A a = new A(); B b = new B(); //多态 A a = new B();
可以很明显的看出讲多态后,= 右边 new 的类型可以和前面不一样了,但这个不一样是有规定的,= 右边必须是左边的子类(或子接口)。
到这就是多态?这是刚学多态很懵逼的时候,感觉听完还是无法讲出多态是个什么。
多态就像你的电脑,除了你的主机,还应该有显示器、鼠标和键盘,它们连起来才能形成一个整体电脑。多态也是这样,你得把其他知识点学完,结合一起才能理解什么是多态。
接下讲多态的方法运行:
先上代码看运行结果
public class A {
public void fun(int i) {
System.out.println("A " + i);
}
}
public class B extends A {
@Override
public void fun(int i) {
System.out.println("B " + i);
}
public void funB() {
System.out.println("B funB");
}
}
public class Test {
public static void main(String[] args) {
A a = new B();
a.fun(10);
//a.funB(); //编译报错
}
}
运行结果:

到这可能有一个问题:不是new的B类吗,怎么调用funB()就报错了。
其实用这段代码讲多态很容易让新人摸不着头脑,下面我们用上文提到的面试题进行解答为什么执行是这样的结果。
先讲结论:编译看左边,运行看右边。
修改代码:这段代码不难,一定要完全看懂才能听懂下面的讲述。
public class A {
public void fun(int i) {
System.out.println("A " + i);
}
}
//A的子类1
public class B extends A {
@Override
public void fun(int i) {
System.out.println("B " + i);
}
public void funB() {
System.out.println("B funB");
}
}
//A的子类2
public class C extends A {
@Override
public void fun(int i) {
System.out.println("C " + i);
}
}
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入0或1:");
int i = sc.nextInt();
A a = null;
switch(i) {
case 0: a = new B(); break;
case 1: a = new C(); break;
}
a.fun(10);
//a.funB(); //编译报错。
}
}
执行结果:

我们现在的情况就是A有了两个子类B、C,我们写代码后还得进行编译,编译时Test的main方法还没执行,它是无法知道 a 的右边到底是 new B() 还是 new C() 的,所以编译器只能通过 = 左边的引用类型进行判断 a 进行调用的方法存不存在,a 中都没有 B 的 funB(),那自然也就编译报错,这就是编译看左边。
当我们程序进行执行的时候,程序走完switch时自然也就知道到底new的是谁了,a 调用 fun() 时,也就去 = 右边的对象中去找对应的方法执行了,这就是运行看右边。
讲到这,多态还没完,先上代码:
public class A {
int i = 10;
}
public class B extends A {
int i = 20;
}
public class C extends A {
int i = 30;
}
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入0或1:");
int i = sc.nextInt();
A a = null;
switch(i) {
case 0: a = new B(); break;
case 1: a = new C(); break;
}
System.out.println(a.i);
}
}
执行结果:

你这条咸鱼自己咸就算了,还骗人,讲的编译看左,运行看右都是骗人的。其实是没讲错的,只是编译看左,运行看右只能适用于方法。下面解释为什么在属性这就行不通了。
别忘了我上文让你死记的多态成立的必备条件,条件中有一条可以进行重写,属性是不存在重写这个概念的(这个是继承的知识),属性也就不存在多态这个概念了,不能运行看右边了,a 是 A 类型,自然也就调用 A 中的属性了。
至于重载为什么不是多态,这个我在这就不进行讲述了(说白了就是菜、懒),别人的博客有,弄懂多态,也就能看的懂了。
最后再声明一遍,这只是一条咸鱼的见解,有误之处多担待(毕竟我人怂胆子小,技术还菜。。。),学的时候请保持质疑的态度。
浙公网安备 33010602011771号