OO Abstraction 出现在类级设计期间,目的是隐藏实现复杂性如何实现 API/设计/系统提供的功能,在某种意义上简化了访问底层实现的“接口”。
抽象的过程可以在类的越来越“更高”的层次(层)上重复,这样就可以在不增加代码的复杂性和每一层的理解的情况下构建大型系统。
例如,Java 开发人员可以利用 FileInputStream 的高级特性,而无需关心它是如何工作的(即文件句柄、文件系统安全检查、内存分配和缓冲将在内部进行管理,并且对消费者)。这允许更改FileInputStream 的实现,并且只要FileInputStream 的API(接口)保持一致,针对以前版本构建的代码仍然可以工作。
同样,在设计自己的类时,您会希望尽可能对其他人隐藏内部实现细节。
在Booch定义1中,OO封装是通过Information Hiding实现的,特别是围绕隐藏类实例拥有的内部数据(表示状态的字段/成员),通过强制以受控方式访问内部数据,并防止对这些字段的直接、外部更改,以及隐藏类的任何内部实现方法(例如,通过将它们设为私有)。
例如,默认情况下可以将类的字段设置为private,并且只有在需要对这些字段进行外部访问时,才会从班上。 (在现代 OO 语言中,字段可以标记为 readonly / final / immutable,这进一步限制了更改,即使在类内也是如此)。
未应用任何信息隐藏的示例(不良做法):
class Foo {
// BAD - NOT Encapsulated - code external to the class can change this field directly
// Class Foo has no control over the range of values which could be set.
public int notEncapsulated;
}
应用字段封装的示例:
class Bar {
// Improvement - access restricted only to this class
private int encapsulatedPercentageField;
// The state of Bar (and its fields) can now be changed in a controlled manner
public void setEncapsulatedField(int percentageValue) {
if (percentageValue >= 0 && percentageValue <= 100) {
encapsulatedPercentageField = percentageValue;
}
// else throw ... out of range
}
}
字段的不可变/仅构造函数初始化示例:
class Baz {
private final int immutableField;
public void Baz(int onlyValue) {
// ... As above, can also check that onlyValue is valid
immutableField = onlyValue;
}
// Further change of `immutableField` outside of the constructor is NOT permitted, even within the same class
}
Re:抽象与抽象类
Abstract classes 是促进类之间共性重用的类,但它们本身不能直接用 new() 实例化 - 抽象类必须是子类,并且只能实例化 concrete(非抽象)子类。 Abstraction 和 abstract class 之间可能造成混淆的一个原因是,在 OO 的早期,继承更多地用于实现代码重用(例如,使用关联的抽象基类)。现在composition is generally favoured over inheritance,还有更多的工具可以实现抽象,比如通过接口、事件/委托/函数、特征/混合等。
Re:封装与信息隐藏
封装的含义似乎随着时间的推移而演变,最近,encapsulation在确定哪些方法时也可以更普遍地使用,字段、属性、事件等捆绑到一个类中。
引用维基百科:
在面向对象编程语言的更具体设置中,该概念用于表示信息隐藏机制、捆绑机制或两者的组合。
例如在语句中
我已将数据访问代码封装到它自己的类中
.. encapsulation 的解释大致相当于Separation of Concerns 或Single Responsibility Principal(SOLID 中的“S”),可以说可以用作重构的同义词。
[1] 看过 Booch 的 encapsulation cat picture 后,您将永远无法忘记封装——面向对象分析和设计与应用程序的第 46 页,
第二版