java多态

class A ...{
public String show(D obj)...{
return ("A and D");
}
public String show(A obj)...{
return ("A and A");
}
}
class B extends A...{
public String show(B obj)...{
return ("B and B");
}
public String show(A obj)...{
return ("B and A");
}
}
class C extends B...{}
class D extends B...{}
(二)问题:以下输出结果是什么?

A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println(a1.show(b)); ①
System.out.println(a1.show(c)); ②
System.out.println(a1.show(d)); ③
System.out.println(a2.show(b)); ④
System.out.println(a2.show(c)); ⑤
System.out.println(a2.show(d)); ⑥
System.out.println(b.show(b)); ⑦
System.out.println(b.show(c)); ⑧
System.out.println(b.show(d)); ⑨
(三)答案

① A and A
② A and A
③ A and D
④ B and A
⑤ B and A
⑥ A and D
⑦ B and B
⑧ B and B
⑨ A and D

为什么答案是这样的,对象间是怎样调用的?
提问者: 因为复杂 - 六级
最佳答案
该问题的关键有两点:
一是子类与父类的关系,二是重载方法的调用问题。
子类对象可以直接当成父类对象使用,但反过来就不可以。举例来说,人是父类,学生是人的子类,所以学生对象一定具备人对象的属性,但是人对象就未必具有学生对象的特性。所以学生对象可以当做人对象来使用,但是人对象就不能当做学生对象使用。注意当把子类对象当成父类对象使用时,子类对象将失去所有的子类特性,只保留与父类同名的属性和方法(同名方法不仅是函数名相同,而且参数类型也要一样,否则不予保留)。
一个类中如果定义了重载的方法,则系统在调用方法时,会根据参数的类型自动选择调用合适的方法。

1 a1.shows(b),在A中没有含有B类参数的方法,但是含有A类参数的方法,根据子类对象父类可用的原则,所以调用方法
public String show(A obj)...{return ("A and A");}

2 a1.show(c),C类是B类的子类,而B类又是A类的子类,所以C类对象可以当制作A类对象使用。结果同上。

3 a1.show(d),根据参数类型直接调用A中的方法
public String show(D obj)...{
return ("A and D");
}

4 a2.show(b),a2本来是一个B对象,但是将其赋给了A类变量,所以a2只保留了与父类A同名的属性和方法。a2.show(b)调用B类中的保留的与父类同名同参方法
public String show(A obj)...{
return ("B and A");
}

5 a2.show(c),B类的保留方法中没有C类参数方法,但是有含有C的父类A的参数方法,所以调用的方法
public String show(A obj)...{
return ("B and A");
}
6 a2.show(d),调用的是A类中的
public String show(D obj)...{
return ("A and D");
}
7 b.show(b),调用B类中的
public String show(B obj)...{
return ("B and B");
}
8 b.show(c),B类中没有C类参数的方法,但是有B类参数的方法,所以调用方法 public String show(B obj)...{
return ("B and B");
}
9 b.show(d),解释同8
你要明白这一点,多态这个做法..多态的作用就是能使你的程序更通用.
就比如:A a = new B;..这代码只能B只能是A的子类或子类的子子类也性.多态你所编写的类型(即A a;)必须是B你上级.换一种说法就比如:A就是动物,B就是猫,你可以把这只猫看作是动物.这样行吧.但你不能把一直动物看作是猫吧.即你所定义的类型必须是实际对象的父类,或是有间接的实现和继承的关系.

例子:A a = new B;就是说B要是间接或直接的继承类和实现接口.方可这样写.

1.第一个输出调用语句: a1.show(b); 你上面答案是"A and A" ;

你先看看: A a2 = new B(); 这里是泛化了吧.也就是说"B"类型可以说是"A"类型.
再看看: A a1 = new A(); 如果再调用a1.show(b);这里这个方法传进来的参数是"b"(即: 'B b = new B()');那么b你可以看作是个"A"类型的是吧?.可是A类里面有两个show()方法即方法重载.
请先看第一个方法:public String show(D obj)
方法里面接受的参数是D类型的.那么你能把B类型的看作是D类性的吗(即:你不可能把一只动物看作是猫吧.)? 即D类型不是B类型的父类.
再看看第二个方法:public String show(A obj)
这个方法就不用说了.这方法接受的参数是A类型的.那么B继承了A.也就可以说B类型的可以泛化成A类型的.还个角度说,就是猫可以看作是一个动物吧.
所以.第一个输出system.out.print(a1.show(b)),这结果自然是:"A and A"

以现实中的事情举个例子:

假设有一个“小提琴演奏者”类,有一个“钢琴演奏者”类,还有一个“萨克斯演奏者”类。它们都是弹奏乐器的,都继承自“乐器演奏者”类。“乐器演奏者”类有个方法叫做“演奏”。三种不同的子类有不同的“演奏”方法实现(拉、弹、吹)。

那么指挥家如果要指挥一个交响乐,那么有两个办法:
一,分别说“小提琴拉起来”、“钢琴弹起来”、“萨克斯吹起来”
二,只需要说一句“乐器们都演奏起来”

显然第一种方法是很笨拙的。因为指挥家不需要知道每种乐器演奏者具体怎么样去演奏乐器(是吹还是弹还是拉),他只需要指挥就可以了。因此应当采用第二种做法。
那么如何实现第二种做法呢?那就是把三种乐器演奏者子类看成是“乐器演奏者”父类。指挥家只需要调用“演奏”方法就可以了。至于具体是怎么去演奏,指挥家是不管的。

虽然代码上写的是把具体的演奏者子类看成了父类,调用的是父类的“演奏”方法,但是因为子类继承了父类的“演奏”方法并且重写为更加具体的实现(拉或者弹或者吹),创建实例的时候创建的是子类的实例(构造方法是子类的,只不过看成是父类去用),所以实际执行的时候会去调用子类的“演奏”方法。因此,究竟是该拉还是该弹还是该吹,指挥家不必在意,这个判断由java虚拟机完成了。

这个就是一个多态的应用

综合各个方面的问题,我个人总结了其它人的答案,并且加入些容易理解的解释,希望对你有好处
1 a1.shows(b),在A中没有含有B类参数的方法,但是含有A类参数的方法,根据子类对象父类可用的原则,所以调用方法
public String show(A obj)...{return ("A and A");}

2 a1.show(c),C类是B类的子类,而B类又是A类的子类,所以C类对象可以当制作A类对象使用根据子类对象父类可用的原则。结果同上。

3 a1.show(d),根据参数类型直接调用A中的方法
public String show(D obj)...{
return ("A and D");
}

4 a2.show(b),a2本来是一个B对象,但是将其赋给了A类变量,所以a2只保留了与父类A同名的属性和方法。就是说只能调用 public String show(D obj)...{
return ("A and D");
}
和 public String show(A obj)...{
return ("B and A");
}
方法根据子类对象父类可用的原则a2.show(b)调用后者,所以:public String show(A obj)...{
return ("B and A");
}

5 a2.show(c),B类的保留方法中没有C类参数方法,但是有含有C的父类A的参数方法,所以调用的方法
public String show(A obj)...{
return ("B and A");
} 备注4和5的关系类似于1和2的关系
6 a2.show(d),调用的是A类中的(为什么调用A类的方法,在4中已经说明)
public String show(D obj)...{
return ("A and D");
}
7 b.show(b),调用B类中的
public String show(B obj)...{
return ("B and B");
}这个是比较直接的,应该容易理解吧
8 b.show(c),B类中没有C类参数的方法,但是有B类参数的方法,所以调用方法(更加详细请看第一条 ) public String show(B obj)...{
return ("B and B");
}
9 b.show(d),解释同8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值