【问题标题】:Confused about Polymorphism [duplicate]对多态性感到困惑[重复]
【发布时间】:2020-08-21 05:13:17
【问题描述】:

我经常阅读多态性的定义,如下所示:

多态是拥有不同类型对象的能力 理解相同的信息

但如果我们不使用多态性,上述定义也适用,例如,如果我们有一个 Circle 类型的对象,其方法为 draw(),另一个类型为 Rectangle 的对象,其方法为 draw() ,我们可以这样做:

circle1.draw();
rectangle1.draw();

所以circle1rectangle1 在不使用多态的情况下理解了同一条消息draw()

我错过了什么吗?

【问题讨论】:

  • 这里的两个 draw 调用并不是真正的 same 消息,是吗?我不能对未知对象(可能是CircleRectangle)、draw 说,并期望他们理解,可以吗?
  • 嗨,你在这里所做的隐藏了多态性。这个想法是你有一些更远的 Circle 和 Rectangle 接口,你可以在 ScreenRefresh 类中创建一些绘制方法。该绘制方法将绘制您拥有的所有“效果”、动画、粒子和形状。理想情况下,它将所有内容存储在 Drawable 数组中,并在循环中执行 item.draw()。
  • 简单的答案是消息不是draw(),而是Circle.draw()Rectangle.draw()。如果有一个公共基类Shapecircle1rectangle1 都会理解消息Shape.draw()——在这种情况下是公共消息。
  • @Sweeper “虽然这两个draw call并不是真正的相同消息,是吗?”我们可以说circle1.draw()没有发送draw()消息到circle1,而是发送Circle.draw() 消息?如果我们做Shape shape1 = new Circle(); shape1.draw();(假设ShapeCircle的超类),那么shape1不会向Circle对象发送draw()消息,而是发送Shape.draw()消息(因此Circle 对象现在可以理解两条消息:Circle.draw()Shape.draw(),这两条消息具有相同的实现/消息处理程序)?
  • @Tom 我的意思是Shape.drawCircle.drawShapeCircle 是不相关类型的条件下是不同的消息,OP 似乎暗示了“没有多态性”这句话.如果Circle 继承自Shape,我会说它们是相同的消息。

标签: java oop polymorphism


【解决方案1】:

在您的示例中,您只有两个不同的类,“绘制”方法是相同的,但这不是 polimorpfhism。

但是,如果您有这样的接口或抽象类:

public class pol {
    public static void main(String[] args) {
        Shape[] shapes = {new Circle(), new Rectangle()};
        for(Shape s: shapes) {
            s.draw();
        }
    }
}

interface Shape {
    void draw();
}

class Circle implements Shape{

    @Override
    public void draw() {
        System.out.println("Circle");
    }
}

class Rectangle implements Shape{

    @Override
    public void draw() {
        System.out.println("Rectangle");
    }
}

然后,即使您将其作为 Shape 访问,每个单独的方法 draw 也会被执行。所以输出将是:

Circle
Rectangle

【讨论】:

    【解决方案2】:

    我想分享一个基本的例子:

    interface Shape{
     void draw();
    }
    
    class Circle implements Shape{
    
        @Override
        void draw(){
        //Draw Circle here.
        }
    }
    
    class Rectangle implements Shape{
    
        @Override
        void draw(){
        //Draw Rectangle here.
        }
    }
    

    所以在你的例子中:

    circle1.draw();
    rectangle1.draw();
    

    您可以安全地调用圆形和矩形对象的 draw 方法,因为它们实际上都是形状。 circle1 既是圆形又是形状,矩形 1 既是矩形又是形状。也就是多态,对象可以有多个类型。

    【讨论】:

      【解决方案3】:

      你提到的draw()方法是完全不同的,属于不同的类。 是的,在多态中,对象理解方法签名,但有一点不同。 例如,假设他们有一个方法可以在两个对象中设置直径,如果没有多态性,您必须像您拥有的对象一样实现该方法! 但是例如以自己的方式为每个对象定义区域,因为它们确实不同。

      【讨论】:

        【解决方案4】:

        以防万一您不喜欢技术性答案...

        理解多态性的一种方法是“一种使代码与做同一件事的各种方法交互的方法,而不知道它是如何做到的。”

        假设您有一个打印数据的程序。这个概念非常广泛,因此您首先要从 txt 文件中读取它。
        您将您的班级称为“TxtReader”。
        实现之后,你很快意识到txt并不是保存数据的好方法......
        所以你决定使用数据库。
        现在你看看你的代码,它被硬编码为使用 TxtReader.read()。

        更改以前被证明有效的代码是一个糟糕的主意,因为它可能会引入新问题。
        所以 -
        你创建了一个名为“Reader”的接口,并给它一个方法“read()”。

        现在你回到你的代码,让 TxtReader 实现 Reader。 然后将代码更改为 Reader.read()。 现在你可以实现任意数量的 Reader 实现,例如 SqlReader、HtmlReader、PhpReader 等,只要它包含方法 read()。

        现在,所有这些实现都可以根据需要变形为一个简单的 Reader。

        这使您可以编写代码,而不必过多担心可能会有哪些实现。 所以我们喜欢使用接口。

        这对于单个程序员来说节省了一点时间,但对于任何类型的项目来说,如果有不止一个人在做同样的工作,这将是一个巨大的时间和金钱节省。

        【讨论】:

          猜你喜欢
          • 2018-03-18
          • 2015-02-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-20
          相关资源
          最近更新 更多