个人对于多态的见解

首先排出一句让我看了发笑的话:

重载和多态无关 - 百度百科

现在似乎已经被改掉了

提前声明

本篇文章十分主观,可能也有错误阐述,欢迎纠错。

因为有许多的单词并没有中文翻译,或者个人认为翻译不恰当,所以有的直接用英文来阐述。(我才不管翻译得对不对,我就这么理解)

不需要硬翻译成中文,毕竟可能会发生像“自函子范畴上的幺半群”这种奇怪的事情(范畴论的东西,借了群里相似结构的名字罢了)。

多态的种类

  1. Ad hoc polymorphism
  2. Parametric polymorphism
  3. Subtyping (Subtype Polymorphism)
  4. Row Polymorphism
  5. Polytypism

其实还有一些其他的,但是其实在实际开发中比较重要的就是这五个中的前三个

Ad hoc polymorphism

polymorphic functions can be applied to arguments of different types, because a polymorphic function can denote a number of distinct and potentially heterogeneous implementations depending on the type of argument(s) to which it is applied.

-Wikipedia

如果你不太想看上面这段英文的话,可以直接看我的理解。

这里给一段 C++ 的栗子:

1
2
3
4
5
6
7
8
9
10
int add(int a, int b)
{
return a + b;
}

// unreasonable but whatever
double add(double a, double b)
{
return a + b + 9032;
}

在这里请注意上面那段维基引用之中的:函数能够通过被应用的参数的不同类型来选择不同的实现方式。

这话什么意思?

Overload ,函数重载。

行,先把百度百科的头锤爆。

Parametric polymorphism

Using parametric polymorphism, a function or a data type can be written generically so that it can handle values identically without depending on their type.

-Wikipedia

还是先放Wiki的阐述。

对数据进行统一操作,而不在意它们的类型。

其实就是 Generic Types ,泛型。

同样都是一个函数接受多种参数类型,那么 ParametricAd hoc 的区别呢?

Thus, ad hoc polymorphism can generally only support a limited number of such distinct types, since a separate implementation has to be provided for each type.

-Wikipedia

Ad hoc 基本上会对每种不同的参数类型有不同的实现方式,因此数量有限;

Parametric 对所有参数类型一视同仁,都是同一种实现。

然后再贴一段 C++ STL 里的东西:

1
2
3
4
5
6
7
8
9
10
11
template <class T>
class vector
{
// ...

void push_back(T&& val) {
// ... do push back
}

// ...
}

这是 std::vector 的声明,一般的 oop 语言类库中的容器类都会用到泛型。

为什么不给 Java 的呢,因为 Java 嘛…

SubTyping

subtyping allows a function to be written to take an object of a certain type T, but also work correctly, if passed an object that belongs to a type S that is a subtype of T.

-Wikipedia

这东西就很好理解了,字面意思,子类多态。

体现在代码上的话就是类之间的继承关系,能出现父类对象的地方,必定能出现子类对象(里氏代换原则)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Super
{
public:
virtual void func()
{
std::cout << 9527 << std::endl;
}
}
class Sub
: public Super
{
public:
void func() override
{
std::cout << "Stephen Chow" << std::endl;
}
}
void invoker(Super& object)
{
object.func();
}

int main()
{
Sub sub;
invoker(sub); // Stephen Chow
}

以下是我对 Override 的理解:

所有的类的 non-static 方法,都隐式包含了一个参数: this ,其类型不言而喻。子类对父类中的方法进行重写,实际上就是改变了参数表的第一个参数的类型。

Override 是一种特殊的 Overload

那么自然,Override ,函数重写(或者说覆盖),就是基于 SubTypingAd hoc polymorphism 的一种体现。

总结

上面三者几乎囊括了 oop 语言中的所有多态,可以这样说:

  • 重载是 Ad hoc polymorphism 的体现;
  • 泛型是 Parametric polymorphism 的体现;
  • 继承是 Subtyping 的体现。

参考文献: