37

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

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

4

13 回答 13

51

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

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

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

例如,最好有一个返回 asList<FlyingMachine>而不是ArrayList<FlyingMachine>. 这样,我可以将方法中的实现更改为 aLinkedList或 aStack而不会破坏任何使用我的方法的代码。

于 2012-06-16T14:49:24.457 回答
27

当两者都给我相同的答案时,多态性的优势是flm.fly()什么j.fly()

优点是

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

返回

"Start, Taxi, Fly"

代替

"No implementation"

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

这意味着您可以编写与类型对象一起使用的方法,FlyingMachine并为其提供各种子类型,例如JetorHelicopter并且这些方法总是会做正确的事情,即调用fly()适当类型的方法而不是总是做同样的事情,即输出"No implementation".

多态性

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

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

  • FlyingMachineb) 当您可以在不更改任何现有逻辑的情况下向应用程序添加新的 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");
    }
}

解释

a)MakeThingsFly该类可以处理所有类型为FlyingMachine.

b)letTheMachinesFly当您添加新类时,该方法也可以在没有任何更改(!)的情况下工作,例如PropellerPlane

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

这就是多态性的力量。你可以用它实现开闭原则

于 2015-10-02T14:06:44.590 回答
15

使用多态性的原因是当您构建通用框架时,该框架采用了一大堆具有相同接口的不同对象。当你创建一个新的对象类型时,你不需要改变框架来适应新的对象类型,只要它遵循对象的“规则”。

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

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

只要每种类型的 FlyingMachine 都定义了合适的 LandPlane 方法,它就可以正常着陆。机场不需要知道任何关于 FlyingMachine 的信息,除了要让飞机降落,它需要在 FlyingMachine 上调用 LandPlane。所以机场不再需要改变,并且可以继续接受新型飞行器,无论是滑翔机、不明飞行物、降落伞等。

因此,多态性对于围绕这些对象构建的框架很有用,它们可以通用地访问这些方法而无需更改。

于 2012-06-16T15:04:01.703 回答
10

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

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

于 2012-06-16T15:30:08.127 回答
6

多态性(运行时和编译时)在 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

于 2017-06-06T18:37:13.280 回答
4

如果您只拥有 Jets,它不会增加太多,当您拥有不同的 FlyingMachines(例如飞机)时,优势就会出现

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

于 2012-06-16T14:52:28.617 回答
3

两者都给你相同的答案flm.fly()j.fly()因为实例的类型实际上是相同的,即Jet,所以它们的行为相同。

当您执行以下操作时,您会看到不同之处:

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

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

多态性被定义为具有不同行为的相同方法签名。如您所见,两者FlyingMachinesJet定义fly()了方法,但是方法的实现方式不同,这认为行为不同。

于 2012-06-16T14:51:36.010 回答
3

让我们在其中再添加一个类,它可以帮助您理解多态性的使用..

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
于 2017-03-29T09:00:06.390 回答
3

多态性还可以帮助我们的代码删除旨在生成生产级代码的“if”条件,因为删除条件会增加代码的可读性并帮助我们编写更好的单元测试用例,我们知道“n”如果有 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();
于 2016-12-03T13:39:30.377 回答
1

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

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

在开始之前绘制软件领域的 ER(实体关系)图总是一个好主意。那是因为您被迫描绘将要创建哪种实体,并且如果您有足够的能力,您可以节省大量代码来查找实体之间的共同行为。但是保存代码并不是一个好的项目的唯一好处。

您可能有兴趣找出所谓的“软件工程”,它是允许您编写“干净代码”的技术和概念的集合(还有一本名为“干净代码”的好书,程序广泛推荐) .

于 2015-10-02T14:20:40.763 回答
0

java为什么需要多态性的一个很好的原因是这个概念被广泛用于实现继承。它在允许具有不同内部结构的对象共享相同的外部接口方面发挥着重要作用。

于 2014-04-13T05:49:55.403 回答
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";
    }
}

覆盖

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

重载

可以具有具有不同签名的相同名称的行为。例如,某位总统说得很清楚,但另一位总统却只说得很大声。

于 2014-01-09T07:11:34.463 回答
0

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

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

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

在这里,我们可以有一个基类机器,start()stop()的方法是和,每个机器类型都可以扩展这个功能和@Override这些方法。

于 2018-05-17T14:21:28.117 回答