多态 (计算机科学)

多态 (计算机科学)

特设多态

编辑

主条目:特设多态和名字修饰

克里斯托弗·斯特雷奇选择术语“特设多态”来指称一个多态函数可以应用于有不同类型的实际参数上,但是以来它们所应用到的实际参数类型而有不同的表现(也叫做为函数重载或运算符重载)[6]。在这个上下文中术语“特设”(ad hoc)不意图表达贬义,它只是简单的指出这种多态不是类型系统的基本特征。在下面的Pascal/Delphi例子中,在查看Add函数的调用的时候,它好像通用的工作在各种类型之上,但编译器对所有意图和用途都把它们视为完全不同的两个函数:

program Adhoc;

function Add(x, y : Integer) : Integer;

begin

Add := x + y

end;

function Add(s, t : String) : String;

begin

Add := Concat(s, t)

end;

begin

Writeln(Add(1, 2)); (* 打印"3" *)

Writeln(Add('Hello, ', 'Mammals!')); (* 打印"Hello, Mammals!" *)

end.

在动态类型语言中情况可能更加复杂,因为需要调用的正确函数只能在运行时间确定。

隐式类型转换也被定义为多态的一种形式,叫做“强迫多态”[2][7]。

参数多态

编辑

主条目:参数多态和泛型编程

参数多态允许函数或数据类型被一般性的书写,从而它可以“统一”的处理值而不用依赖于它们的类型[8]。参数多态是使语言更加有表现力而仍维持完全的静态类型安全的一种方式。这种函数和数据类型被分别称为“泛化函数”和“泛化数据类型”从而形成了泛型编程的基础。

例如,可以构造连接两个列表的一个函数append,它不关心元素的类型:它可以附加整数的列表、实数的列表、字符串的列表等等。设定“类型变量a”来指定这个列表中元素的类型。接着append可以确定类型:

forall a. [a] × [a] -> [a]

这里的[a]指示具有类型a的元素的列表类型。我们称对于a的所有的值,append的类型“由a参数化”。结果的列表必须由相同类型的元素组成。对于应用append的每个位置,都要为a确定一个值。

参数多态的概念适用于数据类型和函数二者。可以被求值或应用于不同类型的值之上的函数叫做“多态函数”。看起来具有泛化类型性质的数据类型(比如具有任意类型的元素的列表)被指认为“多态数据类型”,就像根据它来做特殊化的泛化类型那样。

参数多态在函数式编程之中是普遍的,在这里它经常被简称为“多态”。下面的Haskell例子展示了参数化列表数据类型和在其上的两个参数多态函数:

data List a = Nil | Cons a (List a)

length :: List a -> Integer

length Nil = 0

length (Cons x xs) = 1 + length xs

map :: (a -> b) -> List a -> List b

map f Nil = Nil

map f (Cons x xs) = Cons (f x) (map f xs)

参数多态在很多面向对象语言中也能获得到。例如,C++和D的模板,和在C#、Delphi和Java中所称谓的泛型:

class List {

class Node {

T elem;

Node next;

}

Node head;

int length() { ... }

}

List map(Func f, List xs) {

...

}

John C. Reynolds(英语:John C. Reynolds)(和后来的Jean-Yves Girard(英语:Jean-Yves Girard))正式的将这种多态概念发展为对lambda演算的扩展(叫做多态lambda演算或系统F)。任何参数多态函数都必然在能做什么上受到限制,工作在数据的形状而不是它的值之上,这导致了parametricity(英语:parametricity)的概念。

子类型

编辑

主条目:子类型和虚函数

在面向对象程序设计中,计算机程序執行時,相同的訊息可能會送給多個不同的類別之物件,而系統可依據物件所屬類別,引發對應類別的方法,而有不同的行為。簡單來說,所謂多型意指相同的訊息給予不同的物件會引發不同的動作。比如有動物之類別,而且由動物繼承出類別貓和類別狗,並對同一源自類別動物(父類別)之一訊息有不同的響應,如類別動物有「叫」之動作,而類別貓會「喵喵」,類別狗則會「汪汪」,則稱之為多型態。

在下面的这个例子中猫和狗都是动物的子类型。过程letsHear()接受一个动物,但在传递给它一个子类型的时候也能正确工作:

abstract class Animal {

abstract String talk();

}

class Cat extends Animal {

String talk() {

return "Meow!";

}

}

class Dog extends Animal {

String talk() {

return "Woof!";

}

}

static void letsHear(final Animal a) {

println(a.talk());

}

static void main(String[] args) {

letsHear(new Cat());

letsHear(new Dog());

}

多态可分为变量多态与函数多态。变量多态是指:基类型的变量(对于C++是引用或指针)可以被赋值基类型对象,也可以被赋值派生类型的对象。函数多态是指,相同的函数调用界面(函数名与实参表),传送给一个对象变量,可以有不同的行为,这视该对象变量所指向的对象类型而定。多态也可定义为“一种将不同的特殊行为和单个泛化记号相关联的能力”,变量多态是函数多态的基础。

相关推荐

乒乓球混合团体世界杯赛程表!附12月8日cctv5乒乓直播表
战争机器4怎么安装
365提款不到账的吗

战争机器4怎么安装

📅 07-11 👁️ 3580
盗版系统的风险与危害(探究使用盗版系统的后果及解决之道)