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

What is the main difference between Inheritance and Polymorphism?

今天模块开卷考试结束时,我被问到这个问题,结果发现自己迷路了。我读的是Head first Java,两个定义似乎完全相同。我只是想知道我自己的想法主要有什么不同。我知道有许多类似的问题,但是,我没有看到提供一个明确的答案。


继承是指"class"从现有的"class"派生。所以如果你有一个Person类,那么你有一个扩展PersonStudent类,Student继承了Person所拥有的一切。关于您亲自在字段/方法上设置的访问修饰符,有一些细节,但这是基本的想法。例如,如果在Person上有一个私有字段,那么Student将看不到它,因为它的私有字段和私有字段对子类不可见。

多态性处理程序如何决定它应该使用哪些方法,这取决于它拥有什么类型的东西。如果您有一个Person,它有一个read方法,而您有一个Student扩展了Person,它有自己的read实现,那么哪个方法被调用是由运行时决定的,这取决于您有一个PersonStudent方法。这有点棘手,但如果你做一些像

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

调用学生的read方法。这就是多态性的作用。你可以这样做,因为一个Student是一个Person,但运行时足够聪明,知道实际类型的p是学生。

注意,不同语言的细节不同。例如,您可以在JavaScript中继承继承,但与Java中的继承方式完全不同。


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

多态性是指改变子类中一个超类的行为。


多态性:以相似的方式处理不同类型对象的能力。例子:长颈鹿和鳄鱼都是动物,动物可以长到1(0)。如果您有一个Animal的实例,那么您可以调用Move而不知道或不关心它是什么类型的动物。

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

其他形式的多态性:还有其他实现多态性的方法,例如接口,它只提供多态性,但不提供代码重用(有时代码非常不同,例如蛇的Move),与狗的Move)大不相同,在这种情况下,接口是更好的多态性选择。

在其他动态语言中,多态性可以通过duck类型实现,即类甚至不需要共享相同的基类或接口,它们只需要一个同名的方法。或者更动态的,比如javascript,你甚至不需要类,只需要一个方法名相同的对象就可以多态使用。


主要区别是多态性是遗传的一种特殊结果。多态性是在运行时根据对象类型确定要调用的方法的地方。当一个类从另一个类继承并重写特定方法时,就会出现这种情况。但是,在正常的继承树中,您不必重写任何方法,因此并非所有方法调用都必须是多态的。这有道理吗?这是一个类似的问题,所有的福特汽车都是汽车,但不是所有的汽车都是福特(虽然不是完全…)。

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


在Java中,两者是密切相关的。这是因为Java使用了一种叫做"动态调度"的方法调用技术。如果我有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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继承了a的spin,但是,当我们试图像处理a类型一样处理对象时,我们仍然得到b对draw的行为。draw行为具有多态性。

在某些语言中,多态性和继承并没有那么紧密地联系在一起。例如,在C++中,未声明虚函数是继承的,但不会动态调度,因此即使使用继承也不会得到多态行为。

在JavaScript中,每一个函数调用都是动态调度的,并且您的输入很弱。这意味着您可以有一堆不相关的对象,每个对象都有自己的draw,有一个函数迭代它们并调用函数,每个对象的行为都很好。你不需要继承就可以绘制自己的多态图。


多态性:假设你在一家卖钢笔的公司工作。所以你可以做一个很好的班级,叫做"笔",它可以处理你需要知道的关于笔的所有事情。您可以编写各种类型的账单、发货、创建发票,所有这些都使用pen类。一天,老板来了,说:"好消息!公司正在成长,我们现在正在销售书籍和CD!"这不是什么好消息,因为现在你必须改变每门使用钢笔的课程,同时使用书籍和CD。但是,如果您最初创建了一个名为"可销售产品"的接口,然后Pen实现了这个接口,该怎么办?然后您可以编写所有的装运、发票等类来使用该接口而不是笔。现在,您需要做的就是创建一个名为Book&CompactDisc的新类,它实现了可销售产品接口。由于多态性,所有其他类都可以继续工作而不会发生变化!有道理?

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

多义性可以在类/接口中实现,但继承总是在2个或更多类/接口之间。继承总是符合"is-a"关系,而不是总是具有多态性(它可以同时符合"is-a"/"has-a"关系)。


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

例如。

1
2
3
4
// 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中定义的foo。


Oracle文档准确地引用了这一差异。

继承:一个类从它的所有超类继承字段和方法,无论是直接的还是间接的。子类可以重写它继承的方法,也可以隐藏它继承的字段或方法。(请注意,隐藏字段通常是不好的编程实践。)

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

多态性不适用于字段。

相关职位:

多态性vs覆盖vs过载


继承是一个与代码重用相关的概念。例如,如果我有一个父类称为Animal,它包含某些属性和方法(例如,makeNoise()sleep()并且我创建了两个名为DogCat的子类。因为狗和猫都以同样的方式睡觉(我假设),所以在父类Animal提供的DogCat子类中,不需要为sleep()方法添加更多的功能。然而,一只Dog吠叫和一只Cat喵叫,所以尽管Animal类可能有发出噪音的方法,但狗和猫相对彼此和其他动物发出不同的声音。因此,需要重新定义特定类型的行为。因此多态性的定义。希望这有帮助。


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


多态性是一种遗传效应。它只能在相互扩展的类中发生。它允许您在不知道类的确切类型的情况下调用类的方法。同样,多态性也会在运行时发生。

例如,Java多态性示例:

enter image description here

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

例如,Java平台中的所有类都是对象的子孙(图像礼貌Oracle):

enter image description here

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


如果你使用JAVA,它就是这么简单:

多态性是使用继承的方法,但是"重写"它们来做不同的事情(或者如果您称之为super-so,那么在技术上也不会是多态的)。

如果我错了就纠正我。


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


继承是一种多态性,确切地说,继承是动态多态性。所以,当您删除继承时,就不能再覆盖它了。


多态性是通过在Java中的遗传来实现的。

1
2
3
4
5
6
7
public class Animal {}
public interface Herbivore {}
public interface Carnivore {}
public interface Pet {}

public class Hamster extends Animal implements Herbivore implements Pet () {}
public class Cat extends Animal implements Carnivore implements Pet () {}

Hamster类继承了AnimalHerbivorePet的结构,表现出家养宠物的多态行为。

Cat类继承了AnimalCarnivorePet的结构,也表现出家养宠物的多态行为。


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

在继承中,子类继承超级类的属性。