如何快速为类创建许多类似的插槽?

时间:2012-03-14 23:36:48

标签: macros lisp common-lisp

我有以下课程,更像他们:

(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))))

2 个答案:

答案 0 :(得分:2)

对你想要的功能的覆盖率不是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>

答案 1 :(得分:1)

恕我直言,您似乎需要一个包含三个字段damagesliceblunt)的课程pierce。您可以在weaponattack等内使用该类