这真的是多态吗?

3
考虑一个名为Shape的接口,它有一个draw()方法。两个类TriangleCircle实现了Shape接口并覆盖了draw()方法。 现在在main中我有下面这段代码:
public static void main(String[] args){

    Shape shape = new Triangle();
    shape.draw();

    //Shape shape = new Circle();
    //shape.draw();
}

我认为这是多态的一个例子,因为我们在运行时不知道将调用哪个绘制方法。解释说:“在调用shape.draw()时,编译器在编译时看到Shape接口中的draw(),而JVM在运行时调用Triangle类中的draw()。Circle类中的draw()也是如此。” 我的疑问是,这真的可以称为多态吗?由于new Triangle()或new Circle()是硬编码的,编译器是否总是知道它指向子类的draw()方法?

请参阅多态性 - Seelenvirtuose
请注意Java教程 http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html - SubOptimal
重复的本地变量 shape! - OnePunchMan
“编译器不会一直知道程序的行为吗?” - 不,它不会。通常情况下,没有实际运行程序是无法推断出其行为的。 - The Paramagnetic Croissant
1
将您的方法更改为:void mainDraw(Shape s) {s.draw();},编译器就不会知道它将从哪里调用以及将传递哪个参数(圆形、三角形等)。 - Nir Alfasi
5个回答

4

运行时多态的概念可以通过一个工厂方法来进行最好的解释,该方法基于输入返回一个形状对象。

工厂方法:

public static Shape getShape(int i){ 
              if(i == 1) {return new Triangle();}
              else{return new Circle();}  
}

属性文件:

num:1

根据属性文件中的值,获取Shape对象。

public static void main(String[] args){

   int x = getFromPropertyFile();
   Shape shape = getShape(x); // Shape obtained from a factory method
   shape.draw(); //Runtime polymorphism
}

编译器不知道将返回哪个对象。它由输入提供的值在运行时决定。您可以在 JDBC 驱动程序实现中看到这种实现,其中实现类在运行时确定。
在您的示例中:
Shape shape = new Triangle();
shape.draw();

Shape shape = new Circle();
shape.draw();

方法绑定发生在编译时,也就是说在编译时决定可以在给定引用类型上调用哪些方法。

方法的执行实现选择发生在运行时,也就是说,在运行时决定要执行哪个方法实现,即超类版本或其中一个子类版本。


1

同意,就像我的例子一样 ;o) - Vitaly

0

让我们使用数组来编写相同的示例:

public static void main(String[] args){
    Shape[] shapes = new Shape[2];
    shapes[0] = new Triangle();    
    shapes[1] = new Circle();
    for(int i=0;i<shapes.length;++i){
        shape.draw();
    }
}

从我的角度来看,这是更好的多态性说明。希望能对你有所帮助。


0

为了实现多态性,您可以尝试这个方法

    public static void main(String[] args){

        SampleClass sample=new SampleClass(new Triangle() or new Circle())
                sample.draw();
       }

    Clas SampleClass
    {
    Shape shape;
    //constructor
     public SampleClass(Shape shape)
    {
         this.shape=shape;

     }
       public void draw()
     {
            shape.draw();
      }

}

0

你正在使用父引用引用子对象,因此在编译时无法知道调用哪个draw()方法。

此外,你的编译器没有抛出任何错误并允许你的代码被编译,因为它知道shape有一个名为draw的方法,而不知道Triangle或Circle是否有该方法。对于编译器来说,唯一重要的是当你执行shape.draw()时,draw方法的可访问性。你可以尝试只在Triangle中放置一个方法,并尝试使用shape.xxx调用它,编译器将不允许相同的操作。

现在,上述两个事情可以得出结论:A. 我们看到了多态性,可以在编译时解决,我们称之为静态多态性(例如,你的编译器允许你通过父引用访问子引用)B. 在运行时,尽管你说shape.draw,但它仍然调用了子类的draw方法,这只能在运行时解决,因此将其命名为运行时多态性。

我希望我解决了你的疑惑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接