Как вы переопределяете значение по умолчанию для поля в классе? - PullRequest
0 голосов
/ 07 октября 2018

На сегодняшний день это лучший способ переопределить значения полей по умолчанию в классе:

(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.Каким образом планируется поддерживать систему классов Racket?

1 Ответ

0 голосов
/ 29 октября 2018

Прежде всего, ваш пример делает то, что вы, вероятно, не хотите.Использование init-field создает изменяемое открытое поле для экземпляров вашего класса, которое инициализируется соответствующим аргументом инициализации.Они используются не очень часто: чаще используется закрытое поле (например, define) и метод получения, возможно, с установщиком, если вы хотите поддерживать мутацию.Фактически, мы можем сказать, что, однако canvas% использует эти аргументы инициализации, он не сохраняет их как открытые поля, поскольку (как и в случае с методами) класс не может создать новое поле с тем же внешним именем, что и полесвоего суперкласса.(Поля могут быть унаследованы с inherit-field.) Например, при вычислении этого выражения возникает исключение:

(class (class object%
         (init-field [x 1])
         (super-new))
  (init-field [x 2])
  (super-new [x x]))

Для аргументов инициализации, которые вы не хотите хранить в качестве полей, используйте вместо этого initinit-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 мог бы также легко пройти на уровне модуля,но:

  1. Локальные макросы - это круто;и

  2. Одна из замечательных особенностей макросов заключается в том, что вам не нужно обрабатывать общий случай: скажем, может быть, иногда вы хотите передать другие аргументы super-new.Вы, конечно, можете поддержать это, если хотите, но с макросами ни вы, ни автор библиотеки не должны заранее предвидеть все возможные удобства, которые вы захотите.Полностью законно написать простой макрос, который сделает ваш конкретный код более читабельным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...