我可以在CL中模仿不同的构造函数吗?
要详细说明-例如在C ++中,我可以根据传递的参数为同一个类创建不同的构造函数。
我可以用CLOS做到吗?可能有不同的initialize-instance
关键字参数或类似的内容?
答案 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
。