使用混合或继承更新字段的默认值
Update the default value of a field with a mixin or inheritance
假设我有一些 class snack
,字段为 banana?
:
(define snack%
(class object%
(super-new)
(init-field [banana? #f])))
这样做,我可以构造我的 snack%
是否有 banana?
,默认情况下没有 banana?
:
(get-field banana? (new snack%))
(get-field banana? (new snack%
[banana? #f]))
(get-field banana? (new snack%
[banana? #t]))
评估为:
#f
#f
#t
符合预期。
但是,现在我想构建一个 snack-mixin
class,它需要一个 snack%
class(或者实际上,任何 class banana?
字段),并将该字段的默认值更改为 #t
.
不幸的是,我似乎无法找到一种方法来修改继承的 class(如 mixin 中所定义)的默认值。我无法修改它,然后在我调用 super-new
之后 set-field!
,就像我在这里所做的那样:
(define (snack-mixin %)
(class %
(super-new)
(set-field! banana? this #t)))
虽然这确实将默认值从 #f
更改为 #t
(get-field banana? (new (snack-mixin snack%))) ; => #t
它还有一个负面影响,即忽略传递到 banana?
字段的任何内容,并将其设置为 #t
:
(get-field banana? (new (snack-mixin snack%)
[banana? #f]))
; => #t
我有什么方法可以做一个 mixin,或者做一个 class 来继承 snack%
并保持相同的字段 banana?
(如,不创建新字段), 但更改了默认值,同时仍然让用户在调用 new
?
时选择它
你在那里使用的 super-new
形式实际上可以接受参数,就像 new
通常可以的那样。因此,只需创建您自己的 init
表单,构造一些默认为 #t
的 internal-banana?
对象,然后将其传递给 super-new
,如此处完成:
(define (snack-mixin %)
(class %
(init [(internal-banana? banana?) #t])
(super-new [banana? internal-banana?])))
使用此版本的 snack-mixin
,您将获得所需的行为,banana?
字段默认为 #t
,也可以设置为 #f
:
(get-field banana? (new (snack-mixin snack%)))
(get-field banana? (new (snack-mixin snack%)
[banana? #f]))
(get-field banana? (new (snack-mixin snack%)
[banana? #t]))
计算结果为:
#t
#f
#t
符合预期。
编辑:正如 Asumu 所指出的,您实际上不需要使用标识符 internal-banana?
:
(define (snack-mixin %)
(class %
(init [banana? #t])
(super-new [banana? banana?])))
但是,这意味着 banana?
变量和 class 中的 banana?
字段将绑定到两个单独的变量。
假设我有一些 class snack
,字段为 banana?
:
(define snack%
(class object%
(super-new)
(init-field [banana? #f])))
这样做,我可以构造我的 snack%
是否有 banana?
,默认情况下没有 banana?
:
(get-field banana? (new snack%))
(get-field banana? (new snack%
[banana? #f]))
(get-field banana? (new snack%
[banana? #t]))
评估为:
#f
#f
#t
符合预期。
但是,现在我想构建一个 snack-mixin
class,它需要一个 snack%
class(或者实际上,任何 class banana?
字段),并将该字段的默认值更改为 #t
.
不幸的是,我似乎无法找到一种方法来修改继承的 class(如 mixin 中所定义)的默认值。我无法修改它,然后在我调用 super-new
之后 set-field!
,就像我在这里所做的那样:
(define (snack-mixin %)
(class %
(super-new)
(set-field! banana? this #t)))
虽然这确实将默认值从 #f
更改为 #t
(get-field banana? (new (snack-mixin snack%))) ; => #t
它还有一个负面影响,即忽略传递到 banana?
字段的任何内容,并将其设置为 #t
:
(get-field banana? (new (snack-mixin snack%)
[banana? #f]))
; => #t
我有什么方法可以做一个 mixin,或者做一个 class 来继承 snack%
并保持相同的字段 banana?
(如,不创建新字段), 但更改了默认值,同时仍然让用户在调用 new
?
你在那里使用的 super-new
形式实际上可以接受参数,就像 new
通常可以的那样。因此,只需创建您自己的 init
表单,构造一些默认为 #t
的 internal-banana?
对象,然后将其传递给 super-new
,如此处完成:
(define (snack-mixin %)
(class %
(init [(internal-banana? banana?) #t])
(super-new [banana? internal-banana?])))
使用此版本的 snack-mixin
,您将获得所需的行为,banana?
字段默认为 #t
,也可以设置为 #f
:
(get-field banana? (new (snack-mixin snack%)))
(get-field banana? (new (snack-mixin snack%)
[banana? #f]))
(get-field banana? (new (snack-mixin snack%)
[banana? #t]))
计算结果为:
#t
#f
#t
符合预期。
编辑:正如 Asumu 所指出的,您实际上不需要使用标识符 internal-banana?
:
(define (snack-mixin %)
(class %
(init [banana? #t])
(super-new [banana? banana?])))
但是,这意味着 banana?
变量和 class 中的 banana?
字段将绑定到两个单独的变量。