子类型

维基百科,自由的百科全书
跳转至: 导航搜索

计算机科学中,子类型(subtype)一般是同另一个数据类型(超类型,supertype)有关系的数据类型,通过了某种可代换性概念,这意味着为在这个超类型的元素上运算而写计算机程序也可以在子类型的元素上运算。更明确的说,超类型-子类型关系经常通过Liskov代换原则来定义;但是任何给定编程语言都可以定义它自己的子类型概念,或根本没有这个概念。

例子[编辑]

子类型的例子: 鸟

右图中给出了子类型的一个简单实际例子。一般性对象“鸟”(或超类型)引发了三个派生对象(或子类型)“鸭子”、“杜鹃”和“鸵鸟”。每个都以自己的方式改变了基本的“鸟”的概念,但仍继承了很多“鸟”的特征。一个数据对象可以被声名为这四种类型中任何一个。这个图中使用了 UML 符号,箭头指示方向和超类型和它的子类型之间的联系。

在多数基于类的面向对象编程语言中,子类引出子类型: 如果 AB 的子类,则类 A 的实例可以用在期望类 B 的实例的任何上下文中;所以我们称 AB 的子类型。一个结论就是声明有类型 B 的任何变量或形式参数在运行时间可以持有类 A 的一个值;在这种情况下很多面向对象编程者会声称 B 是这个变量的“静态类型”而 A 是它的“动态类型”。这个规则的例外包括 C++语言中的私有继承(它不建立子类型),和 Eiffel 语言中在派生类型上特定运算,在其中继承自基类的特征可以用违反子类型规则的方式去除或修改。

另一个例子是可以允许整数值被用在期望浮点数值的地方,或可以定义包含整数和实数二者的一个类型 number 的语言。在第一种情况下,整数类型将是浮点数类型的子类型;在第二种情况下,这两个类型都是 number 的子类型而相互之间无子类型关系。

编程者可利用子类型来以比没有它更抽象的方式来写代码。考虑下面的例子:

function max (x as number, y as number) is
  if x < y then
    return y
  else
    return x
end

如果整数和实数都是 number 的子类型,则二者任何类型都可以传递给这个函数。为此,子类型经常被认为是一种形式的多态性。上述例子也可以比较于 C++ 语言的模版

类型论中,子类型关系经常写为 <:,有着 A<:B 意味着 AB 的子类型。在类型论中子类型可用如下事实来特征化,如果 A<:B,类型 A 的任何表达式也可被给予类型 B;立法这个特征化的形式类型规则叫做“包容”规则。

子类型方案[编辑]

类型论理论家区分名义子类型,在其中只有特定方式声明的类型相互之间可以是子类型,和结构子类型,在其中两种类型的结构决定一种类型是否是另一种类型的子类型。上面描述的基于类的面向对象子类型描述是名义的;面向对象的结构子类型规则可以声称,如果类型 A 的一个对象能处理类型 B 的对象能处理的所有消息(就是说,如果它们定义都同样的方法),则 AB 的子类型,不管二者任何一个是否从继承自其他对象。不是对象类型的类型的健壮的结构子类型规则也是周知的。

带有子类型的编程语言实现可分为两大类: 如果 A<:B,在“包含”实现中类型 A 的任何值的表示也表示类型 B 的相同值,在“强制”实现中类型 A 的值可自动的转换成类型 B 的值。在面向对象语言中子类型所导致的子类型通常是包含的;联系整数和浮点数的子类型关系,它们有不同表示,通常是强制的。

在定义子类型关系的几乎所有类型系统中,它是自反的(意味着对于任何类型 AA<:A)和传递的(意味着如果 A<:B 并且 B<:CA<:C)。这得到了在类型上的预序

参见[编辑]

  • 派生类型是给出新类型但结构上同于最初类型的类型。依赖于类型系统,它可以是也可以不是子类型。
  • 基于类的编程有混淆了子类型和子类导致的问题的一个例子。

外部链接[编辑]