多态性的好处[关闭]


71

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

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()

Answers:


72

当您处理列表时,它非常有用...一个简短的示例:

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

或者,当您想允许方法与以下任何子类一起使用时 CoolingMachines


22
显然,这只是它如何有用的一个例子。基本上,您可以拥有通用的API。
user606723 2012年

1
是的,这绝对只是一个例子。为了获得更多的概念上的理解,最好设计一个可伸缩,可读并且可以遵循设计模式的应用程序(在设计类图时很有用)。
唐尼2012年

1
它也旨在遵循Liskov替换原理:该原理指出,如果S是的子类型T,则T可以用THEN代替每次出现S
Shehaaz 2013年

58

如果您确实了解具体的课程,那是没有好处的。但是,在许多情况下,您希望能够编写仅了解基类或接口的代码。

例如,IterablesGuava中查看-很多方法(大多数情况下)并不关心Iterable所使用的实现。您是否真的要为每个实现单独分配所有这些代码?

可以编码到抽象基类或接口的位置,您允许自己以后使用共享相同公共API但可能具有不同实现的其他实现。即使您只想要一个生产实现,也很可能需要其他实现进行测试。(这在很大程度上适用于所讨论的课程。)


4
然后,让我们开始使用诸如依赖注入之类的东西。基于接口的编程具有许多优点。
jcolebrand 2012年

4
@jcolebrand,就像对接口进行测试一样,而不是对实现进行测试。然后,您的单元测试将不在乎是从数据库,平面文件还是凭空获取数据。集成测试应该,但是那是另外一回事了;)
Wayne Werner 2012年

30

因为稍后如果您要使用AirConditioner而不是Refrigerator用于冷却,则仅需要更改的代码是CoolingMachines cm = new AirConditioner();


17

您要使用的原因

CoolingMachines cm = new Refrigerator();

是你以后可以轻松使用不同的语言CoolingMachines。您只需要更改一行代码,其余代码仍然可以使用(因为它将仅使用的方法CoolingMachines,该方法比特定的机器(例如Refrigerator)更通用)。

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


7

第一个答案:

将多态用于方法覆盖和方法重载。在不同类中使用的其他类方法则有两个选择:第一个方法被继承,第二个方法被重写。这里扩展接口:使用它们,或者实现方法:逻辑写它们。用于方法,类继承的多态。

第二个答案:

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

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


7
让我向您介绍我的两个最亲密的朋友,ShiftEnter。欢迎来到我们的社区,但是在这里我们喜欢格式化事情,而不是盲目地打字。另外,我需要您检查所做的更改,并确保它们符合您发布意图。随时编辑。我认为您在声明中犯了一些错误,但我不确定。
jcolebrand 2012年

5

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

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

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

  • 封装:每个类都隐藏其操作的详细信息,并且仅建立在基类的接口上。

  • 关注点分离:许多面向对象的编程都与分配职责有关。谁来负责?特殊问题可以放在子类中。

因此,多态只是更大的oo画面的一部分,使用它的原因有时仅在您尝试进行“真实的” oo编程时才有意义。


4

多态性的一个简单用例是,您可以拥有一个CoolingMachines数组,其中元素0是制冷器,元素1是AirConditioner等。

您无需执行任何检查或确定要处理的对象即可调用跳闸或启动等。

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


2

我将举一个简单易懂的示例。假设您有一些json

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

现在,以编程方式说出您想要列出名称,类型和值。不必为每种类型都使用switch()(数组为a,字符串为sz等),您只需具有基本类型并调用执行其功能的函数即可。与使用十几种类型的开关相比,它还具有更高的CPU效率。

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


1
没错,更不用说添加更多类型来切换语句的维护了!
M3NTA7 2012年

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家族中,并且这些新子类的对象也可以与现有代码一起使用。


3
我认为您向后解释了部分内容。人们使用工厂作为允许多态代码的手段,而不是作为多态代码的终点。
hugomg 2012年

2
我同意missingo的观点,工厂只是处理现代OOP语言(如Java和C#)施加的限制的一种手段。
蒂莫西·鲍德里奇

@missingno那是什么我也想说,工厂使用的多态代码,但也有多态性代码的其他要求也..
VSS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.