封装和抽象之间的确切区别是什么?
这里的大多数答案都集中在OOP上,但封装要早得多:
每个函数都是一个封装 ; 用伪代码:
point x = { 1, 4 } point y = { 23, 42 } numeric d = distance(x, y)
这里,distance封装了平面中两点之间的(欧几里得)距离的计算:隐藏了实现细节。这是封装,纯净而简单。
distance
抽象是泛化的过程:采取具体的实现方式并将其应用于不同的(尽管有些相关)数据类型。抽象的经典示例是C的qsort数据排序功能:
关于的事情qsort是,它不关心排序的数据-实际上,它不知道排序的数据。而是,它的输入类型是无类型指针(void*),这只是C所说的“我不在乎数据类型”(也称为类型擦除)。重要的一点是qsort,无论数据类型如何,始终保持不变的实现。那唯一有改变的是比较功能,它不同于数据类型的数据类型。qsort因此,期望用户将所述比较功能作为函数参数提供。
qsort
void*
封装和抽象密切相关,因此你可以指出它们是真正不可分割的。出于实际目的,这可能是正确的。就是说,这里的封装不是抽象的东西:
class point { numeric x numeric y }
我们封装了点的坐标,但是除了逻辑上将它们分组之外,我们没有实质性地将它们抽象掉。
这是一个非封装的抽象示例:
T pi<T> = 3.1415926535
这是一个具有给定值(π)的通用变量 pi,声明并不关心变量的确切类型。诚然,在实际代码中很难找到这样的东西:抽象实际上总是使用封装。但是,以上内容确实在C ++(14)中通过变量模板存在(=变量的通用模板);语法稍微复杂一些,例如:
pi
template <typename T> constexpr T pi = T{3.1415926535};