日期:2014-05-20  浏览次数:20637 次

初学者多态问题
有关这些代码
Shape   pentagonobj   =   new   Pentagon();

Pentagon是shape的子类

书上对这代码的解释是:
定义一个pentagonobj   做为子类pentagon的实例
而且它将实现shape类,这样做完全正确   实现多态性时   可以创建一个有父类(如shape类)的对像  

但该对像的实际实现是pentagon的!//这句话不明白
也就是说,可以认为对像为shape类型,并且具有对pentagon类型的引用!//这句话更不明白  

谁可以用通俗的语言讲一讲这两句话是什么意思     谢谢了!

------解决方案--------------------
父类的引用可以用父类的构造器来创建,也可以用子类的构造器来。
1. 当用父类构造器来创建时,引用看到的只是父类的方法。
2. 当用子类构造器来创建时,引用看到的只是父类的方法和那些被子类覆盖掉的方法。

Shape pentagonobj = new Pentagon();
Pentagon是shape的子类

这是使用子类的构造器,所以在内存中会按子类来分配内存空间,但引用看到的如上面第二
条所说的。

我们可以通过转换来获得子类的引用,Pentagon pentagon=(Pentagon)pentagonobj .
为什么可以转换呢?因为我们在前面用的是子类构造器,它就是一个子类,当然可以转换了
------解决方案--------------------
/*new Pentagon()的时候,jvm会依次装入Pentagon.class和Shape.class,然后实例化。
实例化的顺序是先创建Shape实例,然后创建Pentagon实例。这一点从构造函数的调用顺序可以看出来。
“new Pentagon()”操作得到的实际是一个Pentagon类型的指针(其实就是一个内存地址),所以说pentagonobj是个Pentagon类型。
但是由于多态的存在,它又被upcating成为Shape类型。
不过upcating后有一点缺陷,就是pentagonobj已经不知道自己是“Pentagon”类型了。
如果Pentagon类实现了Shape类没有的方法,比如“hello”,那么这个方法不能被直接调用。
像这样:
pentagonobj.hello()。是不行的。
必须这样:
((Pentagon)pentagonobj).hello().
*/


public class Shape
{
public Shape()
{
System.out.println( "Shape ");
}

public static void main(String[] args)
{
new Shape();
Shape pentagonobj=new Pentagon();
((Pentagon)pentagonobj).hello();
}

}

class Pentagon extends Shape
{
public Pentagon()
{
super();
System.out.println( "Pentagon ");
}

public void hello()
{
System.out.println( "hello ");
}
}

------解决方案--------------------
这个问题再怎么抽象地讲也是云山雾罩,不如做个试验一目了然。假定你的Shape类中有一个构造函数,有一个draw方法,如下:
class Shape {
public Shape() {
System.out.println( "在Shape的构造函数中。 ");
}
public void draw() {
System.out.println( "Shape类的draw方法。 ");
}
}

class Pentagon extends Shape{
public Pentagon () {
System.out.println( "在Pentagon 的构造函数中。 ");
}
public void draw() {
System.out.println( "Pentagon 类的draw方法。 ");
}
public void paint() {
System.out.println( "Pentagon 类的paint方法。 ");
}
}

到现在为止,我们有两个类,Pentagon继承Shape,两个类都有一个构造函数和一个draw()方法,Pentagon还有一个Shape没有的方法paint();到现在为止,我们可以静态地看到它们的共同点和不同点,是吧?
好,现在把它们放到程序中去运行,看看它们的表现。
public class Poly {
public static void main(String[] args) {
Shape obj = new Pentagon();
obj.draw();
}

编译运行,结果为:
在Shape的构造函数中。
在Pentagon 的构造函数中。
Pentagon 类的draw方法。

现在对照结果回答楼主的问题:
1。该对像的实际实现是pentagon的(类):没错,因为obj调用的是Pentagon的draw方法,所以obj实现的Pentagon类
2。可以认为对像为shape类型,并且具有对pentagon类型的引用:为了印证这句话,现在我们在main方法中加上obj.paint();再编译,咦,程序报错,说找不到paint方法。为什么?
就是因为obj是Shape类型,而Shape类中并没有paint()方法。关于“具有对pentagon类型的引用”,就不讲了,估计越讲越乱。但到此为止,我们至少明白了两点,1。obj是Pentagon类型因为当调用draw方法时他调用的是Pentagon的draw方法;2。obj是Shape方法因为它不认Pentagon特有的paint方法。换句话说obj兼有Shape和Pentagon两个类的共同点。
现在回答楼主的第三个问题:
3。那多态到底有什么好处啊?首先,好处是大大地。我们知道数组可以很方便的定义一系列数据而不必一个一个定义,但有一个缺点,就是每个数组成员的类型必须一样。但有时我们确实需要这样的数组,怎么办,有了多态,问题就好办了。比如,我们有Pentagon、Circle、Rectangle、Triangle和Square五个对象,由于它们都从Shape派生而来,所以我们可以告诉数组说它们都是一个类型,