【问题标题】:How can I quickly create many similar slots for a class?如何快速为一个班级创建许多类似的插槽?
【发布时间】:2012-03-14 23:36:47
【问题描述】:

我有以下课程,而且更喜欢他们:

(defclass weapon ()
  ((base-slice-damage
    :documentation "Base slice damage dealt by weapon"
    :reader base-slice-damage
    :initform 0
    :initarg :base-slice-damage)
   (base-blunt-damage
    :reader base-blunt-damage
    :initform 0
    :initarg :base-blunt-damage)
   (base-pierce-damage
    :reader base-pierce-damage
    :initform 0
    :initarg :base-pierce-damage)))

(defclass dagger (weapon)
  ((base-slice-damage
    :initform 3)
   (base-pierce-damage
    :initform 6)))

(defclass attack ()
  ((slice-damage-dealt
    :initarg :slice-damage-dealt
    :reader slice-damage-dealt)
   (blunt-damage-dealt
    :initarg :blunt-damage-dealt
    :reader blunt-damage-dealt)
   (pierce-damage-dealth
    :initarg :pierce-damage-dealt
    :reader pierce-damage-dealt)))

如您所见,有很多重复。对于其中两个类,我的插槽都具有相同的选项,并且仅根据它们是切片、钝还是穿孔而有所不同。

我考虑过使用宏来定义属性类,然后将它们混合在一起。这就是我目前所拥有的:

(defmacro defattrclass (attr-name &body class-options)
  `(defclass ,(symb attr-name '-attr) ()
     ((,attr-name
       ,@class-options))))

但这还远远不够。


编辑:

我想出了这个,虽然我并不完全满意:

(defmacro defattrclass (attr-name &body class-options)
  `(defclass ,(symb attr-name '-attr) ()
     ((,attr-name
       ,@class-options))))

(defmacro defattrclasses (attr-names &body class-options)
  `(progn
     ,@(loop for attr-name in attr-names collect
            `(defattrclass ,attr-name ,@class-options))))

【问题讨论】:

标签: macros lisp common-lisp


【解决方案1】:

没有完全 100% 覆盖您想要的功能,但我已经使用这个宏有一段时间了:

(defmacro defclass-default (class-name superclasses slots &rest class-options)
  "Shorthand defclass syntax; structure similar to defclass
  Pass three values: slot-name, :initform, and :documentation
  Everything else gets filled in to standard defaults"
  `(defclass 
     ,class-name 
     ,superclasses 
     ,(mapcar (lambda (x) `( ,(first x)
                             :accessor ,(first x)
                             :initarg ,(intern (symbol-name (first x)) "KEYWORD")
                             :initform ,(second x)
                             :documentation ,(third x)))
              slots)
     ,@class-options))

使用方法:

CL-USER> 
(defclass-default weapon ()
  ((base-slice-damage 0 "Base slice damage dealt by a weapon")
   (base-blunt-damage 0 "Needs a doc")
   (base-pierce-damage 0 "Needs a doc")))
#<STANDARD-CLASS WEAPON>
CL-USER>

【讨论】:

  • 这看起来很有帮助,谢谢。我想知道允许插槽变化是否太疯狂了?例如,在某些情况下,我希望我只创建一个阅读器而不是一个访问器。
  • 由你决定;在语言和你的问题之间找到正确的交集;有了宏,你真的可以为所欲为
【解决方案2】:

恕我直言,您似乎需要一个具有三个字段(slicebluntpierce)的类 damage。您可以在 weaponattack 等内部使用该类。

【讨论】:

  • 我正在考虑类似的事情。但是,我也在创建诸如“slice-damage-received”之类的插槽和其他变体。
  • 可能会通过多重继承获得一些牵引力(例如,制作插槽混合)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
  • 1970-01-01
  • 2020-03-15
  • 2014-07-31
  • 1970-01-01
相关资源
最近更新 更多