槽和继承
根据字面含义,他是为了解决当进行类的继承的时候出现的槽名字/槽描述符一样时子类如何继承和取舍。
(defparameter *account* (make-instance 'bank-account))
因为一个类中槽的名字必须是唯一的,虽然这样,但是如果一个类继承了很多的基类,但是这些基类都定义了一个叫balance的槽。处理方式是把同名描述符放到一块,然后去一个唯一的名字(我感觉仍旧是叫balance)
:initform 因为每个类都会指定默认值,新类将使用最相关的那一个。
:initargs 他不需要互斥,就好比一个槽可以有很多个别名来指向他,新的槽描述符将会包含所有的:initargs,make-instance可以调用任何任何一个:initargs来给他赋值。如果有很多个:initargs对同一个槽赋值的话,会使用make-instance中最左边的那个。
When an instance would inherit a slot with the same name from several of its superclasses, the instance inherits a single slot that combines the properties of the slots in the superclasses. The way combination is done varies from propertyto property:
1. The : allocation, :initform(ifany), and :documentation (if any), will be those of the most specific classes.
2. The :initargs will be the union of the :initargs of all the superclasses. So will the .-accessors, : readers, and : writers, effectively.
3. The : type will be the intersection of the : types of all the superclasses.
一个类中:initarg/:accessor 后参数名字一样,如何处理?
当accessor后面一样的函数名一样的时候,如果调用的话,它会选择最下面的那个。Accessor后面跟的是一个函数名,比如我们可以(the-b *Q*)。
CL-USER> (defclass par()
((b :initarg :b :initform "b" :accessor the-b)
(a :initarg :a :initform "a" :accessor the-b)))
#<STANDARD-CLASS PAR>
CL-USER> (defparameter *q* (make-instance 'par)) *Q*
CL-USER> (the-b *Q*) "a"
CL-USER> (setf (the-b *q*) 4) 4
CL-USER> (slot-value *q* 'a) 4
CL-USER> (slot-value *q* 'b) "b"
当父类与子类中的:accessor重复时,如果调用的话,他会返回最相关的那个方法进行处理。
CL-USER> (defclass too-3()
((a :initarg :a-1 :initform "a" :accessor a-a)
(b :initarg :b-1 :initform "b" :accessor b-b)))
#<STANDARD-CLASS TOO-3>
CL-USER> (defclass sub-too-3(too-3)
((a :initarg :a-2 :initform "a3" :accessor b-b)
(b :initarg :a-1 :initform "b3" :accessor b-b2)))
#<STANDARD-CLASS SUB-TOO-3>
CL-USER> (defparameter *kk* (make-instance 'sub-too-3)) *KK*
CL-USER> (b-b *kk*) "a3"
下面是如果把initarg后的形参关键字设置为一样的时候,比如都叫:b的话,你只需要设置一个:b,就可以关联到所有initarg叫:b的槽。
CL-USER> (defclass par()
((b :initarg :b :initform "b" :accessor the-b)
(a :initarg :b :initform "a" :accessor the-b)))
#<STANDARD-CLASS PAR>
CL-USER> (defparameter *t* (make-instance 'par :b "me")) *T*
CL-USER> (slot-value *t* 'a) "me"
CL-USER> (slot-value *t* 'b) "me"
如果父类跟子类中的不同槽的:initarg参数一样,跟上面一样,全部初始化。
CL-USER> (defclass too-2()
((a :initarg :a-1 :initform "a" :accessor a-a)
(b :initarg :b-1 :initform "b" :accessor b-b)))
#<STANDARD-CLASS TOO-2>
CL-USER> (defclass sub-too-2(too-2)
((a :initarg :a-2 :initform "a" :accessor b-b)
(b :initarg :a-1 :initform "b" :accessor b-b2)))
#<STANDARD-CLASS SUB-TOO-2>
CL-USER> (defparameter *uu* (make-instance 'sub-too-2 :a-1 "p")) *UU*
CL-USER> (b-b2 *uu*) "p"
CL-USER> (a-a *uu*) "p"
下图是,当你初始化时,光标放到类后时所指示你可以进行初始化的initargs参数。