【问题标题】:Benefit of Polymorphism [closed]多态性的好处[关闭]
【发布时间】:2012-06-20 09:51:12
【问题描述】:

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

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 对象我可以调用Refrigeratortrip() 方法,但是对于cm 对象,该方法将被隐藏。现在我的问题是我为什么要使用多态或者我为什么要使用

CoolingMachines cm = new Refrigerator();

当我同意时

Refrigerator rf = new Refrigerator();

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

【问题讨论】:

    标签: java oop jakarta-ee polymorphism


    【解决方案1】:

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

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

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

    【讨论】:

    • 这显然只是它如何有用的一个例子。基本上,你可以有通用的 API。
    • 是的,这绝对只是一个例子。为了更深入地理解概念,最好设计一个可扩展、可读且可能遵循设计模式的应用程序(在设计类图时很有用)。
    • 它也被设计为遵守里氏替换原则:该原则指出,如果ST 的子类型,那么T 可以替换每次出现的S
    【解决方案2】:

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

    例如,查看Guava 中的Iterables - 很多方法(大部分)并不关心正在使用Iterable 的哪个实现。您真的希望所有代码分别用于每个实现吗?

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

    【讨论】:

    • 然后让我们开始使用依赖注入之类的东西。基于接口的编程有很多优点。
    • @jcolebrand,比如针对接口进行测试,而不是实现。那么你的单元测试并不关心数据是从数据库、平面文件还是稀薄的空气中提取的。集成测试应该,但那是另一回事;)
    【解决方案3】:

    因为以后如果你想用AirConditioner而不是Refrigerator来冷却,那么你只需要更改代码是CoolingMachines cm = new AirConditioner();

    【讨论】:

      【解决方案4】:

      你要使用的原因

      CoolingMachines cm = new Refrigerator();
      

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

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

      【讨论】:

        【解决方案5】:

        第一个答案:

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

        第二个答案:

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

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

        【讨论】:

        • 让我向您介绍我最亲密的两个朋友ShiftEnter。欢迎来到我们的社区,但在这里我们喜欢格式化,而不是盲目地打字。另外,我需要您查看我所做的更改,并确保它们保持您帖子的意图。随意编辑。我认为您在陈述中犯了一些错误,但我并不完全确定。
        【解决方案6】:

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

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

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

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

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

        因此,多态性只是 oo 大图的一部分,使用它的原因有时只有在您要尝试进行“真正的”oo 编程时才有意义。

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            【解决方案8】:

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

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

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

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

            【讨论】:

            • 不错,更不用说switch语句添加更多类型等维护了!
            【解决方案9】:

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

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

            【讨论】:

            • 我认为您的部分解释倒退了。人们使用工厂作为允许多态代码的一种手段,而不是作为多态代码的终点。
            • 我同意missingo的观点,工厂只是处理Java和C#等现代OOP语言所施加的限制的一种手段。
            • @missingno 这也是我想说的,工厂使用多态代码,但多态代码还有其他要求..
            猜你喜欢
            • 2013-08-06
            • 2014-03-29
            • 2012-07-10
            • 2014-07-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-08-13
            相关资源
            最近更新 更多