在 Racket class 中使用 `private`(和 `define/private`)形式
Use of the `private` (and `define/private`) form in a Racket class
Racket 的 class
s have a private
form that can be used to hide methods. This seems to mimic use of private in other languages like Java or C#. The docs 展示了一个使用 private 隐藏方法的例子:
(define light%
(class object%
(super-new)
(define on? #t)
(define (toggle) (set! on? (not on?)))
(private toggle)
(define (flick) (toggle))
(public flick)))
> (send (new light%) toggle)
send: no such method
method name: toggle
class name: light%
> (send (new light%) flick)
但是,默认方法似乎是私有的,无论是否实际使用了 private
关键字。例如,修改文档中的示例会产生相同的结果:
(define light%
(class object%
(super-new)
(define on? #t)
(define (toggle) (set! on? (not on?)))
(define (flick) (toggle))
(public flick)))
> (send (new light%) toggle)
send: no such method
method name: toggle
class name: light%
> (send (new light%) flick)
在这两种情况下,class 之外的范围无法访问 toggle
,但它们可以访问 flick
,因为它被标记为 public
。
那么,private
是干什么用的,为什么还在语言里呢?
在第二种情况下,toggle
不是方法;它是一个私有字段,其值为闭包。特别是,为每个 light%
对象分配一个新的 toggle
闭包。
使用 (private toggle)
时,toggle
方法定义被转换为采用 this
的额外参数,并且字段引用通过该参数解析。像这样:
(define (toggle-impl this-obj)
(set-light%-on?! this-obj (not (light%-on? this-obj))))
由于它不再关闭 this
,因此可以与 class 同时分配一次过程。 class
宏将 toggle
绑定到一个宏,该宏重写对 toggle
的所有调用以传递隐式 this
参数。 (这就是方法名称不是值的原因;如果你想 map
一个列表上的方法,你必须 eta-expand 所以方法名称在运算符位置。)
Racket 的 class
s have a private
form that can be used to hide methods. This seems to mimic use of private in other languages like Java or C#. The docs 展示了一个使用 private 隐藏方法的例子:
(define light%
(class object%
(super-new)
(define on? #t)
(define (toggle) (set! on? (not on?)))
(private toggle)
(define (flick) (toggle))
(public flick)))
> (send (new light%) toggle)
send: no such method
method name: toggle
class name: light%
> (send (new light%) flick)
但是,默认方法似乎是私有的,无论是否实际使用了 private
关键字。例如,修改文档中的示例会产生相同的结果:
(define light%
(class object%
(super-new)
(define on? #t)
(define (toggle) (set! on? (not on?)))
(define (flick) (toggle))
(public flick)))
> (send (new light%) toggle)
send: no such method
method name: toggle
class name: light%
> (send (new light%) flick)
在这两种情况下,class 之外的范围无法访问 toggle
,但它们可以访问 flick
,因为它被标记为 public
。
那么,private
是干什么用的,为什么还在语言里呢?
在第二种情况下,toggle
不是方法;它是一个私有字段,其值为闭包。特别是,为每个 light%
对象分配一个新的 toggle
闭包。
使用 (private toggle)
时,toggle
方法定义被转换为采用 this
的额外参数,并且字段引用通过该参数解析。像这样:
(define (toggle-impl this-obj)
(set-light%-on?! this-obj (not (light%-on? this-obj))))
由于它不再关闭 this
,因此可以与 class 同时分配一次过程。 class
宏将 toggle
绑定到一个宏,该宏重写对 toggle
的所有调用以传递隐式 this
参数。 (这就是方法名称不是值的原因;如果你想 map
一个列表上的方法,你必须 eta-expand 所以方法名称在运算符位置。)