返回介绍

3.3 对象

发布于 2025-02-20 00:17:07 字数 2866 浏览 0 评论 0 收藏 0

从本质上讲, 函数实现的集合就是对象 !请注意对象并 抽象出类型:函数实现的集合的类型非常具体:它是 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? 返回 #tinsert 返回一个新对象,它的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文