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

Dar*_*ess 162 java oop polymorphism inheritance

我今天在模块开卷考试结束时遇到了这个问题,发现自己迷路了.我正在阅读Head first Java,两个定义似乎完全相同.我只是想知道主要区别在于我自己的想法.我知道有很多类似的问题,但是,我没有看到哪些提供了明确的答案.

hvg*_*des 277

继承是指"类"派生自现有的"类".所以如果你有一个Person类,那么你有一个Student扩展的类Person,Student 继承了所有的东西Person.您在Person中的字段/方法上放置的访问修饰符有一些细节,但这是基本的想法.例如,如果您打开了私有字段Person,Student则不会看到它,因为其私有字段和私有字段对子类不可见.

多态性处理程序如何决定应该使用哪种方法,具体取决于它具有什么类型的东西.如果你有一个Person有一个read方法,并且你有一个Student扩展的Person,它有自己的实现read,那么运行时为你确定调用哪个方法,具体取决于你是否有a Person或a Student.它有点棘手,但是如果你做的话

Person p = new Student();
p.read();
Run Code Online (Sandbox Code Playgroud)

调用Student上的read方法.这就是多态性的作用.您可以执行该分配,因为a Student 是a Person,但运行时足够聪明,可以知道实际的类型pStudent.

请注意,不同语言的细节不同.例如,您可以在javascript中继承,但它与Java中的工作方式完全不同.

  • @ hvgtcodes所以简而言之,超类 - 子类关系是继承和在父类及其子类之间以不同方式实现同​​一方法的概念,并根据情况调用它们是多态性.我对么? (8认同)
  • @PerfectContrast我认为当你想让学生、司机、老师等作为人并将它们分组到列表或其他东西下时,它很有用。因此,当您为所有人调用“read”时,每个人都会调用自己的“read”方法。 (4认同)

Ted*_*opp 194

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

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

  • @ jaco0646 - 在Java的上下文中,我是这么认为的.(在其他语言中,也许不是那么多.)请注意,这里松散地使用"超类"和"子类".多态性也可以表示在接口中指定(但未实现)的行为的继承. (6认同)
  • 这个答案是否意味着多态性需要继承? (4认同)

Dav*_*vy8 61

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

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

其他形式的多态性:还有其他实现多态性的方法,比如接口,它只提供多态性但没有代码重用(有时候代码是完全不同的,比如MoveSnake Move与Dog 会有很大不同,在这种情况下)在这种情况下,接口将是更好的多态选择.

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


Chr*_*son 17

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

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


cco*_*ley 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
Run Code Online (Sandbox Code Playgroud)

然后我们看到B继承spin自A.然而,当我们试图操纵对象就好像它是一个类型A时,我们仍然得到B的行为draw.该draw行为是多态的.

在某些语言中,多态性和继承并不是非常密切相关.例如,在C++中,未声明为虚拟的函数是继承的,但不会动态调度,因此即使使用继承,也不会获得该多态行为.

在javascript中,每个函数调用都是动态调度的,你输入的是弱类.这意味着你可以拥有一堆不相关的对象,每个对象都有自己的对象,draw有一个函数迭代它们并调用函数,每个都表现得很好.你有自己的多态绘制而不需要继承.


Ami*_*itK 12

多态性:假设您为一家销售钢笔的公司工作.所以你创建了一个非常好的类"Pen"来处理你需要了解的关于笔的所有内容.您可以使用Pen类编写各种类别来计费,发货,创建发票.一天的老板来了,说:"好消息!公司正在发展,我们现在正在销售书籍和CD!" 这不是好消息,因为现在你必须改变每个使用Pen的类来使用Book和CD.但是,如果您最初创建了一个名为"SellableProduct"的接口,并且Pen实现了此接口,那该怎么办呢?然后你可以编写所有的发货,发票等类来使用该接口而不是Pen.现在,你所要做的就是创建一个名为Book&CompactDisc的新类,它实现了SellableProduct接口.由于多态性,所有其他类可以继续工作而不会发生变化!合理?

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

在类/接口中可以实现多态,但继承始终在2个或更多类/接口之间.继承总是符合"是-a"关系,而它并不总是与多态性(它可以符合"is-a"/"has-a"关系).


Puc*_*uce 6

继承更像是一个静态的东西(一个类扩展另一个类),而多态是一个动态/运行时的东西(一个对象的行为根据其动态/运行时类型而不是其静态/声明类型).

例如

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

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