不同的初始化,Common Lisp

时间:2019-04-26 00:49:03

标签: class lisp common-lisp

我可以在CL中模仿不同的构造函数吗?

要详细说明-例如在C ++中,我可以根据传递的参数为同一个类创建不同的构造函数。

我可以用CLOS做到吗?可能有不同的initialize-instance关键字参数或类似的内容?

2 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是使用辅助初始化方法:

(defclass myclass ()
  ((s1 :initarg :s1 :accessor s1)))

(defgeneric initialize-myclass (dispatch class &key))

(defmethod initialize-instance :after ((c myclass) &rest args &key (dispatch 'normal)
                                       &allow-other-keys)
  (apply #'initialize-myclass dispatch c args))

(defmethod initialize-myclass ((dispatch (eql 'normal)) (class myclass) &key))

(defmethod initialize-myclass ((dispatch (eql 'special)) (class myclass)
                               &key x &allow-other-keys)
  (print x))

现在你可以说

(make-instance 'myclass :dispatch 'special ...)

例如。请注意,这不一定是一种好方法,但是它确实有效,并且我已经使用了它。另请注意,我可能将关键字参数默认值设置为错误:我不记得您需要在何处说&allow-other-keys和在哪里说,以及在哪里说 right

这里的基本问题是我们希望在其上分发其他东西:initialize-instance可以在正在定义的对象的类上进行分发,但这是可以在其上分发的 all 。特别是它不能分派其关键字参数之一,因为您不能在CLOS中做到这一点。但是我们可以使用其关键字参数之一(此处为dispatch),并将其“祝福”作为辅助初始化泛型函数的位置参数,然后可以对该参数进行分派。

答案 1 :(得分:0)

好吧,initialize-instance通常被定义为一种:after方法,一旦通过make-instance初始化了实例,它就可以进行某种后处理。您可能要做的是使用参数多态性(对参数进行分派),并使用不同的方法根据提供的参数来初始化实例。考虑以下示例:

CL-USER> (defclass my-class ()
       ((a :initarg :a
           :accessor my-class-a)))
#<STANDARD-CLASS COMMON-LISP-USER::MY-CLASS>
CL-USER> (defmethod make-my-class ((a number))
       (make-instance 'my-class :a (format nil "Look ma, a number ~a" a)))
#<STANDARD-METHOD COMMON-LISP-USER::MAKE-MY-CLASS (NUMBER) {1016445273}>
CL-USER> (defmethod make-my-class ((a string))
       (make-instance 'my-class :a (format nil "Look ma, a string ~a" a)))
#<STANDARD-METHOD COMMON-LISP-USER::MAKE-MY-CLASS (STRING) {10166065C3}>
CL-USER> (make-my-class 10)
#<MY-CLASS {1016690E33}>
CL-USER> (my-class-a *)
"Look ma, a number 10"
CL-USER> (make-my-class "foo")
#<MY-CLASS {1016694CD3}>
CL-USER> (my-class-a *)
"Look ma, a string foo"

如您所见,方法make-my-class分派其参数,并相应地初始化my-class