72

当我开始寻找多态性的好处时,我在这里发现了这个问题。但在这里我找不到我的答案。让我告诉我想找到什么。在这里,我有一些课程:

class CoolingMachines{
    public void startMachine(){
        //No implementationion
    }
    public void stopMachine(){
        //No implementationion
    }
}

class Refrigerator extends CoolingMachines{
    public void startMachine(){
        System.out.println("Refrigerator Starts");
    }
    public void stopMachine(){
        System.out.println("Refrigerator Stop");
    }
    public void trip(){
        System.out.println("Refrigerator Trip");
    }
}

class AirConditioner extends CoolingMachines{
    public void startMachine(){
        System.out.println("AC Starts");
    }
    public void stopMachine(){
        System.out.println("AC Stop");
    }
}

public class PolymorphismDemo {
    CoolingMachines cm = new Refrigerator();
    Refrigerator rf = new Refrigerator();
}

现在在这里我在 Demo 类中创建了两个对象,它们是Refrigerator. 我已经完全明白,rf我可以从对象调用 的trip()方法Refrigerator,但该方法将对cm对象隐藏。现在我的问题是我为什么要使用多态性或为什么要使用

CoolingMachines cm = new Refrigerator();

当我没事的时候

Refrigerator rf = new Refrigerator();

多态对象的效率是好还是重量轻?这两个对象的基本目的和区别是什么?cm.start();和有什么区别rf.start()吗?

4

9 回答 9

73

当您处理列表时它很有用......一个简短的例子:

List<CoolingMachines> coolingMachines = ... // a list of CoolingMachines 
for (CoolingMachine current : coolingMachines) {
    current.start();
}

或者当你想让一个方法与任何子类一起工作时CoolingMachines

于 2012-06-18T12:19:55.643 回答
58

如果您对了解具体类真的没问题,那就没有好处了。但是,在许多情况下,您希望能够编写只知道基类或接口的代码。

例如,看看IterablesGuava -有很多方法(大部分)不关心Iterable正在使用什么实现。你真的想要为每个实现单独的所有代码吗?

如果您可以对抽象基类或接口进行编码,您可以稍后使用共享相同公共 API 的其他实现,但可能有不同的实现。即使您只想要一个生产实现,您也可能需要替代实现来进行测试。(这在很大程度上取决于所讨论的类别。)

于 2012-06-18T12:18:39.183 回答
31

因为以后如果您想使用AirConditioner而不是Refrigerator用于冷却,那么您需要更改的代码就是CoolingMachines cm = new AirConditioner();

于 2012-06-18T12:19:59.683 回答
17

您想使用的原因

CoolingMachines cm = new Refrigerator();

是您以后可以轻松使用不同的CoolingMachines. 您只需要更改那一行代码,其余代码仍然可以工作(因为它只会使用 的方法CoolingMachines,这比特定的机器更通用,例如 a Refrigerator)。

因此,对于 的特定实例Refrigerator,调用cm.start();rf.start()工作方式相同,但cm也可能是不同的CoolingMachines对象。并且该对象可能具有不同的start().

于 2012-06-18T12:18:19.883 回答
7

第一个答案:

使用多态性进行方法覆盖和方法重载。不同类中使用的其他类方法然后有两个选项:第一个方法继承,第二个方法覆盖。这里扩展接口:使用它们,或者实现方法:逻辑编写它们。多态性用于方法、类的继承。

第二个答案:

cm.start();和有什么区别rf.start();吗?

是的,两者都是彼此完全不同的对象。不要创建接口对象,因为 Java 不支持接口对象。为接口创建的第一个对象,为冰箱类创建的第二个对象。现在是第二个对象。

于 2012-06-18T12:53:42.457 回答
5

您问题的一般部分(我为什么要使用多态?)的最一般答案是多态实现了一些关键的面向对象设计原则,例如:

  • 代码重用:通过将所有“冷却机”通用的任何代码放入冷却机中,您只需编写一次该代码,对该代码的任何编辑都会立即生效。

  • 抽象:人脑只能记录这么多东西,但他们擅长类别和层次结构。这有助于了解大型程序中正在发生的事情。

  • 封装:每个类都隐藏了它正在做的事情的细节,只是建立在基类的接口上。

  • 关注点分离:很多面向对象的编程都是关于分配职责的。谁来负责这件事?专门的关注点可以放在子类中。

So polymorphism is just part of the bigger oo picture, and the reasons for using it sometimes only make sense if you are going to try and do 'real' oo programming.

于 2012-06-18T21:50:05.437 回答
4

多态性的一个简单用例是您可以拥有一个coolingMachines 数组,其中元素0 是冰箱,元素1 是空调等...

您无需进行任何检查或确定您正在处理的对象即可调用 trip 或 start 等。

当从用户那里获取输入并且必须遍历所有对象并调用类似的函数时,这可能是一个很大的好处

于 2012-06-18T12:21:05.723 回答
2

以多态方式使用对象还有助于创建工厂或相关类的系列,这是实现工厂设计模式的重要部分。这是多态工厂的一个非常基本的示例:

public CoolingMachine CreateCoolingMachines(string machineType)
{
    if(machineType == "ref")
        return new Refrigerator();
    //other else ifs to return other types of CoolingMachine family
}

调用上述代码的用法:

CoolingMachine cm = CreateCoolingMachine("AC"); //the cm variable will have a reference to Airconditioner class which is returned by CreateCoolingMachines() method polymorphically

另外,假设您有一个使用具体类参数的方法如下Refrigerator

public void UseObject(Refrigerator refObject)
{
    //Implementation to use Refrigerator object only
}

现在,如果您将方法的上述实现更改UseObject()为使用最通用的基类参数,则调用代码将有优势以多态方式传递任何参数,然后可以在方法内部使用这些参数UseObject()

public void UseObject(CoolingMachine coolingMachineObject)
{
    //Implementation to use Generic object and all derived objects
}

上面的代码现在更具可扩展性,因为稍后可以将其他子类添加到 CoolingMachines 家族中,并且这些新子类的对象也可以与现有代码一起使用。

于 2012-06-18T12:34:41.847 回答
2

我举一个容易理解的例子。假设你有一些 json

{"a":[1,2],"sz":"text", "v":3, "f":1.2}

现在让我们以编程方式说您想要列出名称、类型和值。而不是为每种类型(a 的数组,sz 的字符串等)都有一个 switch(),您可以只拥有一个基本类型并调用一个完成其工作的函数。它也比使用具有十几种类型的交换机更高效。

然后是带有接口原因的插件、库和外来代码。

于 2012-06-18T21:42:38.090 回答