Mat*_*pos 2 lisp oop common-lisp clos object-initialization
在Python中,我会这样做:
class foo:
def __init__(self):
self.x = self
Run Code Online (Sandbox Code Playgroud)
否则,现在该对象是其自身的参数.我怎样才能在普通的lisp中做到这一点?
(defclass mn ()
((pai :accessor mn-pai
:initarg :pai
:initform self)))
Run Code Online (Sandbox Code Playgroud)
在DEFCLASS 插槽描述中,不能引用对象本身.但是可以编写实例初始化的方法.这与您的Python示例类似.
我们班:
? (defclass foo ()
((bar :accessor foo-bar :initarg :foo)))
#<STANDARD-CLASS FOO>
Run Code Online (Sandbox Code Playgroud)
我们创建了一个:after方法initialize-instance.此通用函数由CLOS提供,其目的是初始化新实例.第一个参数是要初始化的实例.当我们创建类的实例时,Lisp系统将调用该方法foo.
使用访问者foo-bar:
? (defmethod initialize-instance :after ((object foo) &key)
(setf (foo-bar object) object))
#<STANDARD-METHOD INITIALIZE-INSTANCE :AFTER (FOO)>
Run Code Online (Sandbox Code Playgroud)
或通过设置插槽(setf slot-value).
? (defmethod initialize-instance :after ((object foo) &key)
(setf (slot-value object 'bar) object))
#<STANDARD-METHOD INITIALIZE-INSTANCE :AFTER (FOO)>
Run Code Online (Sandbox Code Playgroud)
请注意,我们可以使用任何名称命名实例参数:object或者甚至self.但这个名字没有语义.因为在CLOS中我们有多调度(调度可以解决多个参数并且没有默认的调度参数),所以没有self语义.
现在我们制作然后描述一个类的实例foo:
? (describe (make-instance 'foo))
#<FOO #x302000D20C0D>
Class: #<STANDARD-CLASS FOO>
Wrapper: #<CCL::CLASS-WRAPPER FOO #x302000D2B43D>
Instance slots
BAR: #<FOO #x302000D20C0D>
Run Code Online (Sandbox Code Playgroud)
如您所见,该bar实例的插槽已设置为实例本身.
请注意, 是initform在 的词法上下文中求值defclass,但在 的动态上下文中求值make-instance。这允许您定义一个名为的特殊变量*this*(您可以使用this,但这可能会令人困惑)并在初始化对象时使用它。
(defvar *this*)
Run Code Online (Sandbox Code Playgroud)
为可能引用的类定义一个混合*this*:
(defclass knows-this () ())
(defmethod shared-initialize :around ((object knows-this) slot-names &rest args)
(declare (ignore args))
(let ((*this* object))
(call-next-method)))
Run Code Online (Sandbox Code Playgroud)
例如:
(defclass foo (knows-this)
((myself :initform *this*)))
(describe (make-instance 'foo))
#<FOO {100AC6EF13}>
[standard-object]
Slots with :INSTANCE allocation:
MYSELF = #<FOO {100AC6EF13}>
Run Code Online (Sandbox Code Playgroud)