Is there a way to access slots of superclasses in CLOS?
E.g., in Objective C I can perform
- (void) frob {
[super frob]
}
This sends a message to the (sole) superclass of frob.
Perusing the CLOS documentation suggests that DEFCLASS
merges all superclass information on class creation and thus this ability to communicate with the superclass is lost. Is this correct?
edit:
The scenario is somewhat unusual:
Given classes
(defclass animal ()
((behavior-types
:initform '(:eat :sleep :drink)
:reader behavior-types)))
(defclass cow (animal)
((behavior-types
:initform '(:moo :make-milk)
:reader behavior-types))
(defclass horse
((behavior-types
:initform '(:buck :gambol :neigh)
:reader behavior-types))
How to have a method, say, BEHAVIOR-TYPES
or GET-BEHAVIOR
that, when called with an object of type horse
, returns '(:eat :sleep :drink :buck :gambol :neigh)
. That is to say, inheritance via a slot "adds" to the initform rather than replaces it.
An easy solution is, rather than to assign the data to the class, to have a generic method like so:
(defgeneric behavior-types (obj))
(defmethod behavior-types ((obj animal)) nil)
(defmethod behavior-types :around ((obj animal))
(append '(:eat :sleep :drink)
(call-next-method obj)))
(defmethod behavior-types :around ((obj horse))
(append '(:gambol :neigh :buck)
(call-next-method obj)))
However, this solution moves the data into the defgeneric
rather than the class, where it properly belongs. So the motivation for the question came forth out of this.
At any rate - the question as asked reflected a misunderstanding of CLOS's design. It is not possible, as asked and within the normal framework, to perform this task. However, two separate approaches are given below using the MOP to solve the problem I posed.
The title of your question makes it sound like you're asking about how to access slots, but the code you show seems more like it's about calling methods that have been specialized for the superclass. If it's the latter that you're looking for, you should take a look at
call-next-method
, as well as 7.6 Generic Functions and Methods from the HyperSpec.Calling “superclass methods”
In CLOS, methods don't belong to classes like they do in some other languages. Instead, there are generic functions on which specialized methods are defined. For a given argument list, a number of methods may be applicable, but only one is most specific. You can call the next most specific method with
call-next-method
. In the following transcript, there's a classFOO
and a subclassBAR
, and a generic functionFROB
which has methods specialized forFOO
andBAR
. In the method specialized forBAR
, there's a call tocall-next-method
which, in this case, calls the method specialized forFOO
.Simulating it with method combinations
You can use method combinations to combine the results of the methods that are applicable to a list of arguments. For instance, you can define a method
a
with the method combinationlist
that means when you call(a thing)
, all the methods ona
applicable for the argument are called, and their results are combined into a list. If you give your slots in the different classes different names, and specialize methods ona
that read those values, you can simulate the sort of thing you're looking for. This doens't prevent you from also using a traditional reader that accesses the slot, as well (e.g.,get-a
in the following example). The following code shows an example:Using the MOP
This post from 1998 on Allegro CL archives is worth a read. It sounds like the author is looking for something similar to what you're looking for.
The response (by Heiko Kirschke, not me, but also see this response from Jon White with a similar approach), defines a new type of class:
and specializes
clos:compute-effective-slot-definition
to provide an initform that's computed from the slot definitions of the class and its superclass(es):Then it's used like this:
This is getting into MOP functionality that's not specified by the spec, so you might have to adapt it for your particular implementation. There are some MOP compatibility layer packages out there that might be able to help you out, though.