继承和多态性之间的主要区别是什么?


172

今天的单元开卷考试结束时,我被问到了这个问题,结果发现自己迷路了。我正在阅读Head first Java,这两个定义似乎完全相同。我只是想知道我自己的主观差异是什么。我知道有很多与此类似的问题,但是我没有看到能提供明确答案的问题。



Answers:


288

继承是指“类”源自现有的“类”。所以,如果你有一个Person类,那么你有一个Student扩展类PersonStudent 继承了所有的事情Person了。您在“个人”中的字段/方法上放置的访问修饰符有一些详细信息,但这是基本思想。例如,如果您在上有一个私有字段PersonStudent则不会看到它,因为它的私有字段和私有字段对子类不可见。

多态性处理程序如何决定其应使用的方法,具体取决于程序具有的类型。如果您有一个Person,其中有一个read方法,并且您有一个Student扩展Person,有其自己的实现read,则由运行时为您确定要调用的方法,这取决于您有一个Person还是一个Student。这有点棘手,但是如果您执行类似的操作

Person p = new Student();
p.read();

学生的read方法被调用。多数民众赞成在行动。您可以进行分配,因为a Student 是a Person,但是运行时足够聪明,可以知道a的实际类型pStudent

请注意,语言之间的细节有所不同。例如,您可以在javascript中进行继承,但是它与Java中的工作方式完全不同。


9
简而言之,@hvgtcodes因此,父类与其子类之间的超类-子类关系是继承,并且以不同的方式实现同​​一方法的概念,并根据情况将其称为多态。我对么?
Muhammad Raihan Muhaimin

1
@hvgotcodes,但说如果Personread方法使用公共访问修饰符,Student对象将无法访问它们吗?然后Student s = new Student();会不会更容易?实际上,我仍然还没有真正从多残症中受益。
Scorpiorian83 '17

1
@hvgotcodes Student s = new Student()将起作用。但是让我们说,在您使用此想法编写了许多代码之后,后来您意识到自己犯了一个错误。这个人实际上不是学生,而是老师。因此,您只需将Person p = new Student()更改为Person p = new Teacher(),即可使您的生活变得更加简单。
munmunbb

我的问题是,为什么要使用Person p = new Student();而不是Student p = new Student();
PerfectContrast,

@PerfectContrast我想当您想让学生,驾驶员,老师等作为人员并将您分组在一个列表之内时很有用。因此,当您所有人都调用“读取”时,每个人都调用自己的“读取”方法。
萨凡特

205

继承是指在子类中使用超类的结构和行为

多态性是指更改子类中超类的行为


5
这个答案是否暗示多态性需要继承?
jaco0646

6
@ jaco0646-在Java的上下文中,我认为是这样。(在其他语言中,可能不是那么多。)请注意,此处“宽松类”和“子类”的使用较为宽松。多态还可能意味着在接口中指定(但未实现)行为的继承。
泰德·霍普

1
@AlirezaRahmani-我不明白您的评论。您是说继承不涉及继承属性和行为吗?这将与Java(以及大多数基于类,面向对象的语言)定义继承的方式相反。从Java语言规范的§8.4.8:“类C 从其直接超类继承为其...的超类的所有具体方法mstaticinstance)”(后接有关继承的详细信息)。在我看来,这听起来像是“代码重用”。
Ted Hopp

@TedHopp继承主要是一种多态工具,但是有些人在以后的危险中尝试将其用作重用/共享代码的方式。基本原理是“如果我继承,那么我将免费获得所有方法”,但忽略了这两个类可能没有多态关系的事实。
Alireza Rahmani Khalili

1
@AlirezaRahmani-在Java中(根据标签,OP专门询问了该问题),类继承最肯定涉及继承行为。这是语言定义的一部分。正如您所描述的,这可能被滥用,这是Java的弱点之一。(一个相关的弱点涉及到声明类以简单地导入接口中定义的常量来实现接口。最终,Java设计人员引入import static了消除接口误用的方法。)对于Java中的纯多态性,使用的工具是接口,而不是类继承。
Ted Hopp

63

多态性:以类似方式处理不同类型对象的能力。示例:长颈鹿和鳄鱼都是动物,而动物可以Move。如果您有an的实例,Animal则可以在Move不知道或不关心它是哪种动物的情况下打电话。

继承:这是同时实现多态和代码重用的一种方法。

其他形式的多态性:还有其他实现多态性的方式,例如接口,仅提供多态性,而没有代码重用(有时代码有很大不同,例如MoveSnake与Move与Dog,在这种情况下在这种情况下,接口将是更好的多态选择。

在其他动态语言中,可以通过Duck Typing实现多态,这是这些类甚至不需要共享相同的基类或接口,它们只需要一个具有相同名称的方法即可。甚至像Javascript一样更具动态性,您甚至根本不需要类,只需使用具有相同方法名称的对象即可进行多态使用。


17

主要区别是多态性是继承的特定结果。多态是在运行时根据对象的类型确定要调用的方法的位置。当您让一个类继承自另一个类并覆盖特定方法时,就会出现这种情况。但是,在普通的继承树中,您不必重写任何方法,因此并非所有方法调用都必须是多态的。那有意义吗?这与所有福特汽车都是汽车类似,但并非所有汽车都是福特汽车(尽管并非完全如此。)。

此外,多态处理方法调用,而继承也描述数据成员等。


12

在Java中,两者密切相关。这是因为Java使用一种称为“动态调度”的方法进行技术调用。如果我有

public class A {
  public void draw() { ... }
  public void spin() { ... }
}

public class B extends A {
  public void draw() { ... }
  public void bad() { ... }
}

...

A testObject = new B();

testObject.draw(); // calls B's draw, polymorphic
testObject.spin(); // calls A's spin, inherited by B
testObject.bad(); // compiler error, you are manipulating this as an A

然后,我们看到B继承spin自A。但是,当我们尝试像对待对象是A类型那样操作对象时,仍然会得到B的行为draw。该draw行为是多态的。

在某些语言中,多态性和继承关系不那么紧密。例如,在C ++中,未声明为virtual的函数是继承的,但不会动态分派,因此即使使用继承,也不会获得该多态行为。

在javascript中,每个函数调用都是动态分派的,并且您的输入类型很弱。这意味着您可能有一堆不相关的对象,每个对象都有自己的对象,draw有一个对它们进行迭代的函数并调用该函数,并且每个对象的行为都很好。您将拥有自己的多态绘制而无需继承。


12

多态性:假设您在一家销售笔的公司工作。因此,您创建了一个非常好的类,称为“笔”,该类处理了您需要了解的有关笔的所有信息。您可以使用Pen类编写用于计费,运输,创建发票的各种类。一天,老板来了,说道:“好消息!公司正在成长,我们现在正在出售书籍和CD!” 这不是一个好消息,因为现在您必须更改每个使用Pen的班级,同时还要使用Book&CD。但是,如果您最初创建了一个名为“ SellableProduct”的接口,而Pen则实现了该接口,该怎么办。然后,您可能已经编写了所有运输,发票等类,以使用该接口而不是Pen。现在,您要做的就是创建一个名为Book&CompactDisc的新类,该类实现了SellableProduct接口。由于多态性,所有其他类都可以继续工作而无需更改!合理?

因此,这意味着使用继承是实现多态的一种方法。

多态可以在类/接口中实现,但继承总是在2个或更多类/接口之间。继承始终符合“ is-a”关系,而并非总是具有多态性(多态性可以同时满足“ is-a” /“ has-a”关系。


6

继承是静态的(一个类扩展了另一个类),而多态性是动态的/运行时的东西(对象的行为取决于其动态/运行时的类型而不是其静态/声明的类型)。

例如

// This assignment is possible because B extends A
A a = new B();
// polymorphic call/ access
a.foo();

->尽管a的静态/声明类型是A,但实际的动态/运行时类型是B,因此a.foo()将执行B中定义的foo,而不是A中的。


3

多态是一种在具有相似特征的对象类型之间表达共同行为的方法。它还允许通过覆盖来创建这些特征的变体。继承是通过对象层次结构实现多态的一种方法,其中对象表达关系和抽象行为。它并不是实现多态的唯一方法。原型是表达多态性的另一种方式,它不同于继承。JavaScript是使用原型的语言的示例。我以为还有其他方法。


3

继承是与代码重用有关的概念。例如,如果我有一个父类say,Animal并且它包含某些属性和方法(在本例中为makeNoise()sleep()),那么我将创建两个子类,分别称为DogCat。由于猫和狗都以相同的方式入睡(我会假设),因此无需在父类提供sleep()DogCat子类中为该方法添加更多功能Animal。但是,虽然Dog吠声和Cat叫声如此,Animal上课可能有一种发出声音的方法,狗和猫相对于彼此和其他动物发出不同的声音。因此,需要针对其特定类型重新定义该行为。从而定义了多态性。希望这可以帮助。


3

Oracle文档精确地引用了差异。

继承:类从其所有超类(无论是直接的还是间接的)继承字段和方法子类可以覆盖其继承的方法,也可以隐藏其继承的字段或方法。(请注意,隐藏字段通常是不好的编程习惯。)

多态性: 多态性是指生物学中的一种原理,其中生物或物种可以具有许多不同的形式或阶段。该原理也可以应用于面向对象的编程和Java语言之类的语言。一个类的子类可以定义自己的独特行为,但可以共享父类的某些相同功能。

多态不适用于字段。

相关文章:

多态性vs覆盖vs重载


1

多态继承的影响。它只能在相互扩展的类中发生。它允许您在不知道类的确切类型的情况下调用类的方法。同样,多态性的确在运行时发生。

例如,Java多态示例:

在此处输入图片说明

继承使派生类共享其基类的接口和代码。它发生在编译时

例如,Java平台中的所有类都是对象的后代(图片由Oracle提供):

在此处输入图片说明

要了解有关Java继承Java多态性的更多信息


0

继承是指类A从其所有父级直到对象继承所有非静态受保护/公共方法/字段的时间。


0

如果您使用JAVA,就这么简单:

多态使用的是继承的方法,但是“覆盖”它们可以做一些不同的事情(或者,如果您调用super,则它们是相同的,因此从技术上讲不会是多态的)。

如我错了请纠正我。


0

多态的主要目的:创建超类的引用变量并保存子类 object =>一个对象可以执行多种行为

继承中子类继承超类的属性。



0

使用继承,实现是在超类中定义的-因此行为是继承的。

class Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

class Dog extends Animal;

使用Polymorphism,实现是在子类中定义的-因此仅继承了接口

interface Animal
{
  void move(double newLocation);
}

class Dog implements Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

0

多态性是通过实现继承Java

├── Animal
└── (instances)
    ├── Cat
    ├── Hamster
    ├── Lion
    └── Moose

├── interface-for-diet
   ├── Carnivore
   └── Herbivore
├── interface-for-habitat
   ├── Pet
   └── Wild

public class Animal {
    void breath() {
    };
}

public interface Carnivore {
    void loveMeat();
}

public interface Herbivore {
    void loveGreens();
}

public interface Pet {
    void liveInside();
}

public interface Wild {
    void liveOutside();
}

public class Hamster extends Animal implements Herbivore, Pet {

    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbor is a Gerbil");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat Carrots, Grapes, Tomatoes, and More");
    }
}

public class Cat extends Animal implements Carnivore, Pet {
    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbr is a Gerbil");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Tuna, Chicken, and More");
    }
}

public class Moose extends Animal implements Herbivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat grass");
    }
}

public class Lion extends Animal implements Carnivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Moose");
    }
}

Hamster类继承结构AnimalHerbivorePet表现出多晶型行为主义家养宠物的。

Cat类继承结构AnimalCarnivore并且Pet还具有多态行为主义家养宠物的。

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.