3.3 对象
从本质上讲, 函数实现的集合就是对象 !请注意对象并 未 抽象出类型:函数实现的集合的类型非常具体:它是 Int -> Bool
的函数。当然,正如我们在前面的章节中看到的,对象是函数的泛化,它可以有多个方法。
3.3.1 对象的接口
我们可以定义 对象接口 (interface)的概念,也就是某个对象所有方法的型签(类型签名,signature):
interface Set 是
contains? : Int -> Bool
isEmpty? : Bool
使用我们的简单对象系统实现集合对象:
(define empty
(OBJECT ()
([method contains? (n) #f]
[method isEmpty? () #t])))
(define (insert s val)
(OBJECT ()
([method contains? (n)
(or (eq? val n)
(-> s contains? n))]
[method isEmpty? () #f])))
请注意,empty 是个对象,insert 是返回对象的工厂函数。集合对象实现了 Set 接口。 empty
对象不包含任何值,它的 isEmpty?
返回 #t
。 insert
返回一个新对象,它的 contains?
方法类似于前文中集合的特征函数,而 isEmpty?
返回 #f
。
客户程序中,构造集合部分不用变,与集合对象交互部分就必须用消息发送了:
> (define x empty)
> (define y (insert x 3))
> (define z (insert y 5))
> (-> z contains? 2)
#f
> (-> z contains? 5)
#t
请注意,对象接口本质上就是高阶类型:方法是函数,所以传递对象就是传递函数组。这是高阶函数式编程的推广。面向对象的程序本质上是高阶的。
3.3.2 面向对象编程的原则
原则:对象只能通过其他对象的公共接口来访问它们
一旦创建了对象,比如上面的 z(所绑定的),对它 唯一 能做的就是通过发送消息进行交互。不能“打开对象”。对象的任何属性都不可见,可见的只有它的接口。换一种说法:
原则:对象只对自己有详细的了解
这与 ADT 值有本质区别:在 type-case
的处理中(回忆一下 ADT 实现中用 define-type
实现的 contains?
),我们打开值,从而直接访问其属性。ADT 提供封装,但为 ADT 的客户提供;不为其实现提供。对象在这方面更进一步。即使是对象的方法,其实现也不能访问除自身以外对象的属性。
由此我们可以得出另一个基本原则:
原则:对象就是所有对其可能进行的观测的集合,这些观测通过对象接口定义
这是一条强原则,它表明,如果两个对象在对于特定实验(即一组观测)表现相同,那么它们应该是不可区分的。这意味着使用等值判定操作(如指针相等)违反了 OOP 的这个原则。使用 Java 中的 ==
,我们可以区分即使是 行为 一致的两个对象。
3.3.3 可扩展性
上述原则可以被认为是 OOP 的本质特征。正如 Cook 所说:“ 任何允许区分多个抽象表示的编程模型都 不是 面向对象的 ”。
组件对象模型(COM)是实践中最纯粹的 OO 编程模型之一。COM 遵守上述所有的原则:没有内置的相等性,没有办法确定某个对象是否是某个类的实例。因此 COM 程序是高度可扩展的。
请注意,对象的可扩展性实际上完全独立于继承!(我们的语言甚至还没有类。)它来自对接口的使用。
3.3.4 那 Java 呢?
Java 不是一种纯粹的面向对象的语言,并不是因为它有原始类型(primitive type,也有称作内置类型、基础类型或者基本类型),而是因为它支持的许多操作违反了我们上面描述的原则。Java 内置支持相等 ==
、 instanceof
、转换为类类型,这使得两个对象即使行为一致,也可以被区分。在 Java 中,可以声明一个方法,根据类来接受对象,而不是根据它们的接口(在 Java 中,类名也是类型)。当然还有就是,Java 允许对象访问其他对象的内部(公有字段当然可以,但即使私有字段同一类的对象也可以访问!)。
这意味着 Java 也支持 ADT 风格的编程。这没有什么不对的!但重要的是了解这所涉及的设计上的取舍,然后做出明智的选择。例如,在 JDK 中,某些类在表面上尊重 OO 原则(允许可扩展性),但其实现使用 ADT 技术(不可扩展,但更高效)。如果你有兴趣,参见 List
接口和 LinkedList
实现。
在 Java 中,“纯 OO”编程基本上就是不使用类名称作为类型(即只在 new
之后使用类名),并且从不使用内置的相等( ==
)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论