OO编程中的子类型和继承有什么区别?

时间:2014-05-11 11:40:43

标签: oop computer-science

我找不到主要的区别。当我们可以使用继承并且我们可以使用子类型时,我很困惑。我找到了一些定义,但不是很清楚。

面向对象编程中的子类型和继承有什么区别?

5 个答案:

答案 0 :(得分:25)

除了已经给出的答案之外,这里还有link一篇我认为相关的文章。 摘录:

  

在面向对象的框架中,当在类的层次结构中组织抽象数据类型时,继承通常表现为与子类型密切相关的特性。然而,这两者是正交的想法。

     
      
  • 子类型是指接口的兼容性。如果可以在类型为B的对象上调用可以在A类型的对象上调用的每个函数,则类型AB的子类型。
  •   
  • 继承是指重用实现。如果B的某些函数是根据A的函数编写的,则B类型会继承其他类型A
  •   
     

然而,子类型和继承不需要齐头并进。考虑数据结构deque,一个双端队列。 deque支持两端的插入和删除,因此它有四个函数insert-frontdelete-frontinsert-reardelete-rear。如果我们只使用insert-reardelete-front,我们就会获得正常的队列。另一方面,如果我们只使用insert-frontdelete-front,我们会得到一个堆栈。换句话说,我们可以根据deques实现队列和堆栈,因此数据类型StackQueue继承自Deque。另一方面,StackQueue都不是Deque的子类型,因为它们不支持Deque提供的所有功能。事实上,在这种情况下,DequeStackQueue的子类型!

我认为Java,C ++,C#和他们的同类已经引起了混淆,正如已经指出的那样,它们将这两个想法合并到一个类层次结构中。但是,我认为上面给出的例子以一种与语言无关的方式对这些想法进行公正审判。我相信其他人可以举出更多例子。

答案 1 :(得分:10)

一位亲戚不幸去世了,离开了他的书店。

您现在可以阅读那里的所有书籍,销售它们,您可以查看他的帐户,他的客户列表等。这是继承 - 您拥有亲戚拥有的一切。继承是代码重用的一种形式。

您也可以自己重新打开书店,承担所有相关人员的角色和职责,即使您添加了自己的一些更改 - 这是子类型 - 您现在是书店老板,就像你以前的亲戚一样。

子类型是OOP的一个关键组件 - 你有一个类型的对象,但它满足另一种类型的接口,所以它可以在其他对象可以被使用的任何地方使用。

在您的问题中列出的语言--C ++,Java和C# - 两者(几乎)总是一起使用,因此从某些东西继承的唯一方法是对其进行子类型化,反之亦然。但其他语言并不一定能融合这两个概念。

答案 2 :(得分:6)

继承是关于获取超类型的属性(和/或功能)。例如:

class Base {
    //interface with included definitions

}

class Derived inherits Base {
    //Add some additional functionality.
    //Reuse Base without having to explicitly forward
    //the functions in Base
}

此处,Derived无法在需要Base的情况下使用,但能够与Base行为相似,同时添加行为或更改Base的某些方面的行为。通常,Base将是一个小助手类,它为一些常用功能提供接口和实现。

Subtype-polymorphism是关于实现接口的,因此能够在运行时替换该接口的不同实现:

class Interface {
    //some abstract interface, no definitions included
}

class Implementation implements Interface {
    //provide all the operations 
    //required by the interface
}

此处,Implementation可以在需要Interface的任何地方使用,并且可以在运行时替换不同的实现。目的是允许使用Interface的代码更广泛地使用。

你的困惑是合理的。 Java,C#和C ++都将这两个想法混合成一个单独的层次结构。但是,这两个概念并不相同,并且确实存在将两者分开的语言。

答案 3 :(得分:5)

如果您在C ++中私下继承,则无需子类型即可获得继承。那就是:

class Derived : Base        // note the missing public before Base

你不能写:

Base * p = new Derived();   // type error

因为Derived不是Base的子类型。您只是继承了实现,而不是类型。

答案 4 :(得分:1)

简单来说:子类型和继承都是多态,(继承是一种动态多态 - 覆盖)。实际上,继承是子类化,它意味着在继承中没有保证确保子类与超类的能力(确保子类不丢弃超类行为),但是子类型(例如实现接口和...),确保class不会放弃预期的行为。