Class 如何重写类中字段的默认值?

Class 如何重写类中字段的默认值?,class,inheritance,field,racket,default-value,Class,Inheritance,Field,Racket,Default Value,这是迄今为止我发现的覆盖类中默认字段值的最佳方法: (define sa-canvas% (class canvas% . . . (init-field [min-width 600] [min-height 300] [stretchable-width #f] [stretchable-height #f]) (super-new [min-width min-wid

这是迄今为止我发现的覆盖类中默认字段值的最佳方法:

(define sa-canvas%
  (class canvas%
    . . .
    (init-field [min-width 600]
                [min-height 300]
                [stretchable-width #f]
                [stretchable-height #f])
    (super-new [min-width min-width]
               [min-height min-height]
               [stretchable-width stretchable-width]
               [stretchable-height stretchable-height])
    . . .))

这似乎太冗长了。Racket的类系统设计支持的预期方式是什么?

首先,您的示例做了一些您可能不想要的事情。使用
init field
在初始化为相应初始化参数的类实例上创建一个可变的公共字段。这些并不经常使用:更常见的是使用私有字段(即
define
)和getter方法,如果您想支持变异,可以使用setter。事实上,我们可以看出,尽管
canvas%
使用了这些初始化参数,但它并没有将它们存储为公共字段,因为(与方法一样)类不能创建与其超类字段具有相同外部名称的新字段。(字段可以通过
继承字段
继承)例如,计算此表达式会引发异常:

(class (class object%
         (init-field [x 1])
         (super-new))
  (init-field [x 2])
  (super-new [x x]))
对于不希望保留为字段的初始化参数,请使用
init
而不是
init field
。此表达式与示例相同,但不创建字段:

(class canvas%
  (init [min-width 600]
        [min-height 300]
        [stretchable-width #f]
        [stretchable-height #f])
  (super-new [min-width min-width]
             [min-height min-height]
             [stretchable-width stretchable-width]
             [stretchable-height stretchable-height]))
不过,你是对的,这需要大量的打字和精细的代码来保持同步。类库中没有其他内置方式,但您可以通过一个小宏轻松添加一个:

(class canvas%
  (define-syntax-rule (init/super-new [name default] ...)
    (begin (init [name default] ...)
           (super-new [name name] ...)))
  (init/super-new
   [min-width 600]
   [min-height 300]
   [stretchable-width #f]
   [stretchable-height #f]))
define syntax rule
也可以很容易地在模块级执行,但是:

  • 本地宏很酷;及

  • 宏的一大优点是,您不必处理一般情况:比如说,有时您可能还想将其他参数传递给
    super new
    。如果愿意,您当然可以支持这一点,但是,对于宏,您和库编写器都不必预先预见您可能需要的所有可能的便利。编写一个简单的宏,使您的特定代码更具可读性,这是完全合法的