抽象
想象一个分数类:
class fraction:
int denominator
int numerator
现在有两个对象:
fraction(obj1): denominator=-1 numerator=-1
fraction(obj2): denominator=1 numerator=1
两个对象的值都是 1:(1/1) == (-1)/(-1)。你不会期望他们的行为与外界有任何不同。那是抽象。您将对象保存的数据抽象为逻辑视图,即使在幕后,还有其他事情。从理论上讲,您有一个等价关系,具有不同的等价组:
[1]=(1, 1), (-1, -1), (5, 5), ...
[2]=(2, 4), (-2, -4), ...
...
还有一个抽象函数,将内部细节抽象到外部:
f((1, 1)) = [1]
f((-1, -1)) = [1]
它将具体值映射到对象的抽象值。例如,您可以通过编写一个构造函数映射 (-1, -1) 到 (1, 1) 并为您的类编写一个 equals 函数来做到这一点。
多态性
想象一支笔和两个派生类:
class pen:
void draw(int x, int y)
class pen_thin extends pen:
void draw(int x, int y) { color(x, y) = green; }
class pen_thick extends pen:
void draw(int x, int y) { color(x, y) = green;
color(x, y+1) = green; }
and two objects:
pen_thin(p1)
pen_thick(p2)
两支笔都可以画画。您的一般“笔”无法自行绘制。它只是 pen_thin、pen_thick 和许多其他笔的接口。你说:obj1.draw(1, 0); obj1 是粗笔还是细笔对于您作为用户来说并不重要,对于编译时的编译器也不重要。该调用具有多态性。这是动态多态性(发生在运行时),这就是人们通常的意思。 静态多态发生在编译时:
class colorizer:
void colorize(shirt s)
void colorize(pants p)
这就是所谓的重载。你打电话给obj.colorize(something)。如果你用衬衫引用来调用它,它会调用衬衫的版本。如果你用裤子引用来调用它,它将调用裤子版本。此处所做的选择是在编译时。