在Racket类中使用`private`(和`define / private`)表单

时间:2017-08-10 21:38:58

标签: class oop object racket scoping

球拍的class有一个private表单,可用于隐藏方法。这似乎模仿了Java或C#等其他语言中私有的使用。 The docs显示了使用私有隐藏方法的示例:

(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)

在这两种情况下,课程范围之外的范围都无法访问toggle,但是flick可以访问,因为它标记为public

那么,private用于什么,为什么它仍然在语言中?

1 个答案:

答案 0 :(得分:1)

在第二种情况下,toggle不是一种方法;它是一个私有字段,其值是一个闭包。特别是,为每个toggle对象分配了一个新的light%闭包。

使用(private toggle)toggle方法定义被转换为为this获取额外的参数,并且通过该参数解析字段引用。像这样:

(define (toggle-impl this-obj)
  (set-light%-on?! this-obj (not (light%-on? this-obj))))

由于它不再关闭this,因此该过程可以与该类同时分配一次。 class宏将toggle绑定到宏,该宏重写对toggle的所有调用以传递隐式this参数。 (这就是为什么方法名称不是值;如果你想在列表上map方法,你必须进行eta扩展,以便方法名称在操作员位置。)