为什么要使用多态?

时间:2012-06-16 14:47:39

标签: 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();
    }
}

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

13 个答案:

答案 0 :(得分:33)

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

仅适用于多态的另一个功能是能够拥有List<FlyingMachine>并使用它来存储JetKiteVerySmallPebbles

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

例如,最好让方法返回List<FlyingMachine>而不是ArrayList<FlyingMachine>。这样,我可以将方法中的实现更改为LinkedListStack,而不会破坏使用我的方法的任何代码。

答案 1 :(得分:13)

您使用多态的原因在于您构建通用框架,这些框架将大量不同的对象与相同的接口。创建新类型的对象时,只要它遵循对象的“规则”,就不需要更改框架以适应新的对象类型。

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

//pseudocode
void AllowPlaneToLand(FlyingMachine fm)
{
    fm.LandPlane();
}

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

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

答案 2 :(得分:11)

  

flm.fly()j.fly()时多态性的优势是什么?   给我同样的答案?

优点是

FlyingMachines flm = new Jet();
flm.fly();

返回

"Start, Taxi, Fly"

而不是

"No implementation"

那是多态性。您在fly()类型的对象上调用FlyingMachine,它仍然知道它实际上是Jet并调用相应的fly()方法,而不是输出{ {1}}。

这意味着您可以编写与"No implementation"类型的对象一起使用的方法,并使用各种子类型(如FlyingMachineJet)来提供这些方法,这些方法将始终做正确的事情,即调用适当类型的Helicopter方法而不是总是做同样的事情,即输出fly()

多态性

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

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

  • b)如果您可以在不更改任何现有逻辑的情况下向应用程序添加新的"No implementation".,它也会非常有用。

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

让我说明一下。

代码示例

FlyingMachine

解释

a)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"); } } 类可以处理MakeThingsFly类型的所有内容。

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

PropellerPlane

这就是多态性的力量。您可以使用它实现open-closed-principle

答案 3 :(得分:9)

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

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

答案 4 :(得分:4)

如果您只有Jets,它不会增加很多,当您拥有不同的FlyingMachines时会有好处,例如:飞机

现在您已经修改为包含更多类,多态性的优势在于从您收到的实例的特定类型(和业务概念)中抽象出来,您只关心它可以飞行

答案 5 :(得分:3)

flm.fly()j.fly()都会给出相同的答案,因为实例的类型实际上是相同的,即Jet,因此它们的行为相同。

你可以看到以下区别:

FlyingMachines flm = new FlyingMachines();
flm.fly();

Jet j = new Jet();
j.bombarment();
j.fly();

多态性被定义为具有差异行为的相同方法签名。如您所见,FlyingMachinesJet都定义了方法fly(),但该方法的实现方式不同,其行为方式不同。

请参阅 AA

答案 6 :(得分:2)

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

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

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

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

    List<FlyingMachine> fmList = new ArrayList<>();
    fmList.add(new new JetPlaneExtendingFlyingMachine());
    fmList.add(new PassengerPlanePlaneExtendingFlyingMachine());
    

    以上只能通过多态来完成。否则你必须保留两个单独的列表。

  2. 将一种类型归为另一种:声明对象如:

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

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

  5. 来实现

答案 7 :(得分:1)

多态性也可以帮助我们的代码删除&#34; if&#34;用于生成生产级代码的条件因为删除条件将增加代码可读性并帮助我们编写更好的单元测试用例,我们知道&#34; n&#34;如果案件有n!(n阶乘)可能性。

让我们看看如何

如果你有类FlyingMachine并且在构造函数中接受一个定义FlyMachine类型的字符串,如下所示

class FlyingMachine{

    private type;

    public FlyingMachine(String type){
             this.type = type;
    }

    public int getFlyingSpeedInMph {
         if(type.equals("Jet"))
              return 600;
         if(type.equals("AirPlane"))
              return 300;
    }

 }

我们可以创建两个FlyingMachine实例

 FlyingMachine jet = new FlyingMachine("Jet");
 FlyingMachine airPlane = new FlyingMachine("AirPlane");

并使用

获得速度
 jet.fylingSpeedInMph();
 airPlane.flyingSpeedInMph();

但是如果你使用多态,你将通过扩展泛型FlyMachine类并覆盖getFlyingSpeedInMph来删除if条件,如下所示

class interface FlyingMachine {

     public int abstract getFlyingSpeedInMph;
}


class Jet extends FlyingMachine {
    @Override
    public int getFlyingSpeedInMph(){
          return 600;
    }
}

class Airplane extends FlyingMachine {
    @Override
    public int getFlyingSpeedInMph(){
          return 600;
    }
}

现在你可以获得如下的飞行速度

 FlyingMachine jet = new Jet();
 jet.flyingSpeed();

 FlyingMachine airPlane = new AirPlane();
 airPlane.flyingSpeed();

答案 8 :(得分:0)

多态性如其自身所述,是一个映射了许多的。

java是一种oops语言,所以它通过抽象,重载和覆盖

实现它

记住java不会有运行时多态的规范。

它也有一些最好的例子。

public abstract class Human {

    public abstract String getGender();

}

class Male extends Human
{
    @Override
    public String getGender() {
        return "male";
    }
}

class Female extends Human
{
    @Override
    public String getGender() {
        return "female";
    }
}

<强>重写

重新定义基类的行为。 例如,我想在我的基地Car中移动的现有功能中添加一个速度计数。

<强>重载

可以使用具有不同签名的相同名称的行为。 例如,一位特定的总统说得很清楚,但另一位总统说得很响。

答案 9 :(得分:0)

为什么在java中需要多态性的充分理由是因为该概念被广泛用于实现继承。它在允许具有不同内部结构的对象共享相同的外部接口方面起着重要作用。

答案 10 :(得分:0)

只有在需要多态性时,多态性才能带来益处。 当您的概念项目的实体可以被视为另一个实体的特化时使用它。 主要思想是“专业化”。 一个很好的例子就是所谓的分类学,例如适用于生物。 狗和人都是哺乳动物。 这意味着,Mammals类将所有具有某些属性和行为的实体组合在一起。

此外,ElectricCar和DieselCar是汽车的专业化。 所以两者都有一个isThereFuel(),因为当你开车时,你会想知道是否有足够的燃料来驱动它。 另一个伟大的概念是“期望”。

在开始之前绘制软件域的ER(实体关系)图总是一个好主意。 那是因为你被迫想象将要创建哪种实体,如果你足够,你可以节省很多代码来查找实体之间的常见行为。 但保存代码并不是一个好项目的唯一好处。

您可能有兴趣找到所谓的“软件工程”,它是一组技术和概念,允许您编写“干净的代码”(还有一本名为“清洁代码”的好书,由专业人士广泛建议-grammes)。

答案 11 :(得分:0)

让我们再添加一个类,这有助于您理解多态性的使用。

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

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

class FighterPlan extends FlyingMachines {
    public void fly() {
        System.out.println("Start, Fighter, Fight");
    }
}

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

        FlyingMachines flm2 = new FighterPlan();
        flm2.fly();
    }
}

输出:

Start, Jet, Fly
Start, Fighter, Fight

答案 12 :(得分:0)

这里,对于这个特定的代码,不需要多态性。

让我们理解为什么以及何时需要多态性。

假设有不同种类的机器(如汽车,踏板车,洗衣机,电动机等),我们知道每台机器都会启动和停止。但是每台机器启动和停止机器的逻辑是不同的。在这里,每台机器都有不同的启动和停止实现。因此,为了提供不同的实现,我们需要多态性。

在这里,我们可以使用start()stop()作为其方法的基类机器,每种机器类型都可以扩展此功能并@Override这些方法。