Как я могу быстро создать много похожих слотов для класса? - PullRequest
2 голосов
/ 15 марта 2012

У меня есть следующие классы, и больше на них похожи:

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

2 голосов
/ 15 марта 2012

Не совсем 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 голос
/ 15 марта 2012

ИМХО, похоже, вам нужен класс damage с тремя полями (slice, blunt, pierce). Вы можете использовать этот класс внутри weapon, attack и т. Д.

...