为什么要使用多态?

bai*_*772 30 java polymorphism

我有以下代码,其中有一个父类及其子代.我试图确定代码如何从使用多态性中受益.

class FlyingMachines {
    public void fly() {
        System.out.println("No implementation");
    }
}

class Jet extends FlyingMachines {
    public void fly() {
        System.out.println("Start, Taxi, Fly");
    }

    public void bombardment() {
        System.out.println("Throw Missile");
    }
}

public class PolymorphicTest {
    public static void main(String[] args) {
        FlyingMachines flm = new Jet();
        flm.fly();

        Jet j = new Jet();
        j.bombardment();
        j.fly();
    }
}
Run Code Online (Sandbox Code Playgroud)

多态性的优点是什么,flm.fly()j.fly()给我相同的答案?

Tim*_*ote 39

在您的示例中,多态性的使用并不是非常有用,因为您只有一个子类FlyingMachine.如果您有多种类型,多态性会变得有用FlyingMachine.然后你可以有一个接受任何类型的方法FlyingMachine并使用它的fly()方法.一个例子可能是testMaxAltitude(FlyingMachine).

另一个特点是仅适用于多态性是有能力的List<FlyingMachine>,并用它来存储Jet,KiteVerySmallPebbles.

可以使用多态的最佳案例之一是能够引用接口而不是实现.

例如,最好有一个返回的方法List<FlyingMachine>而不是一个ArrayList<FlyingMachine>.这样,我可以将方法中的实现更改为a LinkedList或者Stack不破坏使用my方法的任何代码.

  • +1,但一个更相关的例子来证明有用性可能是使用`List <FlyingMachine>`而不是`List <Jet>`. (3认同)

Ler*_*rve 16

多态性的优点是什么,flm.fly()j.fly() 给我相同的答案?

优点是

FlyingMachines flm = new Jet();
flm.fly();
Run Code Online (Sandbox Code Playgroud)

回报

"Start, Taxi, Fly"
Run Code Online (Sandbox Code Playgroud)

代替

"No implementation"
Run Code Online (Sandbox Code Playgroud)

这是多态性.你调用fly()一个类型的对象,FlyingMachine它仍然知道它实际上是一个Jet并调用适当的fly()方法而不是输出错误的方法"No implementation".

这意味着你可以编写与类型的对象的工作方法FlyingMachine和各类样亚型喂养它JetHelicopter与这些方法将总是做正确的事,即调用fly()相应类型的方法,而不是总是做同样的事情,即输出"No implementation".

多态性

多态性在您的示例中没有用.

  • a)当你有不同类型的对象并且可以编写可以使用所有这些不同类型的类时,它会变得很有用,因为它们都遵循相同的API.

  • b)当您可以在FlyingMachine不更改任何现有逻辑的情况下向应用程序添加新s 时,它也会非常有用.

a)和b)是同一枚硬币的两面.

让我说明一下.

代码示例

import java.util.ArrayList;
import java.util.List;

import static java.lang.System.out;

public class PolymorphismDemo {

    public static void main(String[] args) {
        List<FlyingMachine> machines = new ArrayList<FlyingMachine>();
        machines.add(new FlyingMachine());
        machines.add(new Jet());
        machines.add(new Helicopter());
        machines.add(new Jet());

        new MakeThingsFly().letTheMachinesFly(machines);
    }
}

class MakeThingsFly {
    public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
        for (FlyingMachine flyingMachine : flyingMachines) {
            flyingMachine.fly();
        }
    }
}

class FlyingMachine {
    public void fly() {
        out.println("No implementation");
    }
}

class Jet extends FlyingMachine {
    @Override
    public void fly() {
        out.println("Start, taxi, fly");
    }

    public void bombardment() {
        out.println("Fire missile");
    }
}

class Helicopter extends FlyingMachine {
    @Override
    public void fly() {
        out.println("Start vertically, hover, fly");
    }
}
Run Code Online (Sandbox Code Playgroud)

说明

a)MakeThingsFly该类可以处理所有类型的东西FlyingMachine.

b)letTheMachinesFly当您添加新类时,该方法也可以无需任何更改(!),例如PropellerPlane:

public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
        for (FlyingMachine flyingMachine : flyingMachines) {
            flyingMachine.fly();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是多态性的力量.你可以用它实现open-closed-principle.


ste*_*918 15

您使用多态的原因是当您构建通用框架时,这些框架会使用相同的接口来获取大量不同的对象.创建新类型的对象时,只要它遵循对象的"规则",就不需要更改框架以适应新的对象类型.

因此,在您的情况下,一个更有用的示例是创建一个接受不同类型的FlyingMachines的对象类型"Airport".机场将定义"AllowPlaneToLand"功能,类似于:

//pseudocode
void AllowPlaneToLand(FlyingMachine fm)
{
    fm.LandPlane();
}
Run Code Online (Sandbox Code Playgroud)

只要每种类型的FlyingMachine定义了一个合适的LandPlane方法,它就可以适当地降落.机场不需要了解FlyingMachine的任何信息,除了要降落飞机,它需要在FlyingMachine上调用LandPlane.所以机场不再需要改变,并且可以继续接受新型的FlyingMachines,无论是手枪,飞碟,降落伞等.

因此,多态性对于围绕这些对象构建的框架非常有用,这些框架通常可以在不必更改的情况下访问这些方法.


小智 10

让我们首先看一下OO设计,继承代表一种IS-A关系,一般我们可以说"让我们FlyingMachines飞".比方说,每个特定的FlyingMachines(子类)IS-A FlyingMachines(父类)都Jet适合这种"让我们FlyingMachines飞行",而我们希望这种飞行实际上是特定的(子类)的飞行功能,即多态性接管.

所以我们以抽象的方式做事,面向接口和基类,实际上并不依赖于细节实现,多态会做正确的事!


Pri*_*jee 6

多态性(运行时和编译时)在 Java 中是必要的,原因有很多。

方法覆盖是运行时多态,重载是编译时多态。

其中很少有(其中一些已经讨论过):

  1. 集合:假设您有多种类型的飞行器,并且希望将它们全部放在一个集合中。您可以定义一个类型列表FlyingMachines并将它们全部添加。

    List<FlyingMachine> fmList = new ArrayList<>();
    fmList.add(new new JetPlaneExtendingFlyingMachine());
    fmList.add(new PassengerPlanePlaneExtendingFlyingMachine());
    
    Run Code Online (Sandbox Code Playgroud)

    以上只能通过多态来完成。否则,您将不得不维护两个单独的列表。

  2. 将一种类型转换为另一种类型:声明如下对象:

    FlyingMachine fm1 = new JetPlaneExtendingFlyingMachine();
    FlyingMachine fm2 = new PassengerPlanePlaneExtendingFlyingMachine();
    fm1 = fm2; //can be done
    
    Run Code Online (Sandbox Code Playgroud)
  3. 重载:与您提供的代码无关,但重载也是另一种多态性,称为编译时多态性

  4. 可以有一个接受类型FlyingMachine处理所有类型的方法,即 FlyingMachine 的子类。只能通过Polymorphism.