通过闭包构建面向对象

By guenchi at 2018-04-26 • 0人收藏 • 289人看过

https://zhuanlan.zhihu.com/p/34064446


词法作用域和闭包一样可以封装“状态”。

(define obj
    (let ((state 1))
      (list
       (lambda () state)
       (lambda (v) (set! state v)))))
       
(define obj-get-state (car obj))
(define obj-set-state (cadr obj))

; test
(obj-get-state)  
; 1
(obj-set-state 2)
(obj-get-state)  
; 2

以上我们定义了一个对象obj,并得到了它的get和set函数,
我们用obj-set-state函数修改状态,用obj-get-state得到内部封装的状态,
发现obj确实封装了状态,从面向对象的意义来看它就是一个“对象”了。

那么面向对象中的类是什么呢?
它其实是一个对象的工厂函数,每次new都创建一个具有独立状态的新对象。
下面我们用闭包模拟一下。

(define create-obj
    (lambda ()
      (let ((state 1))
        (list
         (lambda () state)
         (lambda (v) (set! state v))))))

(define obj1 (create-obj))
(define obj1-get-state (car obj1))
(define obj1-set-state (cadr obj1))

(define obj2 (create-obj))
(define obj2-get-state (car obj2))
(define obj2-set-state (cadr obj2))

; test
(obj1-get-state)  
; 1
(obj1-set-state 2)
(obj1-get-state)  
; 2
(obj2-get-state)  
; 1
(obj2-set-state 3)
(obj2-get-state)  
; 3

我们发现,obj1和obj2独立维护了自身的状态,
而且它们是用同一个工厂create-obj创建出来的,
那么这个工厂函数,就可以类比面向对象中的“类”了。

类的静态变量

在面向对象语言中,某个class是可以有静态变量的,
同一个class的这些变量值是相同的。
那么,我们在create-obj这个工厂函数之上再加一层闭包let好了,
让各个obj共享“类”的变量。

(define let-create-obj
    (let ((hidden 5))
      (lambda ()
        (let ((state 1))
          (list
           (lambda () (+ hidden state))
           (lambda (v) (set! state v)))))))
(define obj1 (let-create-obj))

(define obj1-get-state (car obj1))
(define obj1-set-state (cadr obj1))
(define obj2 (let-create-obj))
(define obj2-get-state (car obj2))
(define obj2-set-state (cadr obj2))
; test(obj1-get-state)  
; 6
(obj1-set-state 2)(obj1-get-state)  
; 7
(obj2-get-state)  
; 6
(obj2-set-state 3)
(obj2-get-state)  
; 8



登录后方可回帖

登 录
信息栏

Scheme中文社区

推荐实现 ChezScheme / r6rs / r7rs large
theschemer.org
Q群: 724577239

精华导览

社区项目

包管理器:Raven
HTTP服务器:Igropyr (希腊火)
官方插件:vscode-chez

社区目标:

完善足以使Scheme工程化和商业化的库,特别是开发极致速度的Web服务器和ANN模块。

一直以来Scheme缺少一个活跃的中文社区,同时中文资料的稀少,导致大多数因为黑客与画家和SICP而接触Scheme的朋友,在学完SICP后无事可做,不能将Scheme转换为实际的生产力。最后渐渐的放弃。
同时Chicken等实现,却因效率问题无法与其他语言竞争。本社区只有一个目的,传播Scheme的文明之火,在最快的编译器实现上,集众人之力发展出足够与其他语言竞争的社区和库。


友情链接:

Clojure 中文论坛
函数式·China


Loading...