我有一个类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的类系统吗?
答案 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