Racket Class

时间:2016-12-09 19:46:13

标签: class object racket

我有一个类counter%,它将一个计数器存储为一个字段,并提供方法get-and-inc,以获取当前计数器的值并递增它。

(define counter%
  (class object%
    (super-new)
    (field [counter 0])
     (define/public (get-and-inc)
      (begin0 counter
              (set! counter (add1 counter))))))

虽然此代码确实可以计算:

> (define x (new counter%))
> (send x get-and-inc)
0
> (send x get-and-inc)
1

问题是柜台现在是公开的:

> (set-field! counter x 42)
> (send x get-and-inc)
42
> (send x get-and-inc)
43

这里的问题是我希望counter字段是私有的,因此实例化该类的人不能修改它。这可以用Racket的类系统吗?

1 个答案:

答案 0 :(得分:1)

是的,有可能。您需要做的就是像在类中的任何其他变量一样定义它:

(define counter%
  (class object%
    (super-new)
    (define counter 0)
    (define/public (get-and-inc)
      (begin0 counter
              (set! counter (add1 counter))))))

现在当你使用它时,每个对象都有自己的计数器:

> (define x (new counter%))
> (define y (new counter%))

> (send x get-and-inc)
0
> (send y get-and-inc)
0
> (send x get-and-inc)
1
> (send y get-and-inc)
1

这是因为在类中定义的非方法的任何变量都被假定为字段(according to the documentation

  

类中的每个字段,init-field和非方法define-values子句声明该类的一个或多个新字段。使用field或init-field声明的字段是公共的。使用inherit-field,子类可以访问和更改公共字段。公共字段也可以通过class-field-accessor访问类外部,也可以通过class-field-mutator访问(参见字段和方法访问)。使用define-values声明的字段只能在类中访问。

这意味着如果您想要一个与该类关联的静态变量,而不是实例化的对象,则需要在该类之外定义它。可能使用let块:

(define static-counter%
  (let ([counter 0])
    (class object%
      (super-new)
      (define/public (get-and-inc)
        (begin0 counter
                (set! counter (add1 counter)))))))

现在所有static-counter个对象都将共享同一个计数器

> (define x (new counter%))
> (define y (new counter%))

> (send x get-and-inc)
0
> (send y get-and-inc)
1
> (send x get-and-inc)
2
> (send y get-and-inc)
3