CLOS - PowerPoint PPT Presentation

About This Presentation
Title:

CLOS

Description:

(defclass ostrich (mammal bird) ((type :initform 'ostrich))) (defmethod lives ((c creature) ... call lives of the mammal class since there is none, it would then ... – PowerPoint PPT presentation

Number of Views:38
Avg rating:3.0/5.0
Slides: 37
Provided by: NKU
Learn more at: https://www.nku.edu
Category:
Tags: clos

less

Transcript and Presenter's Notes

Title: CLOS


1
CLOS
  • To start off with, CLOS (pronounced kloss or
    see-loss) is very different from other object
    oriented programming languages
  • Multiple inheritance is permitted
  • Class members are encapsulated, but methods are
    defined outside of classes, so encapsulation is
    only partial
  • Information hiding is not enforced
  • you can define accessor functions, but there is
    an overriding function, slot-value, that permits
    access to any objects members
  • There is no message passing but instead method
    evocation through generic functions
  • These differences are all made available because
    of the desire to make inheritance more powerful
    than what is available in most other OOPLs
  • Many people feel that CLOS is not a true object
    system whereas others love it

2
CLOS as an OOPL
3
Recall the Structure
  • The original form of object-oriented programming
    was provided by the structure
  • You define the non-homogenous nature by listing
    slots
  • Accessor and constructor functions are generated
    as part of the structure definition, and you can
    define others
  • Single inheritance is available by extending a
    definition
  • Inheritance in this case means to inherit
    everything, and you are not able to override
    previous members (slots) although you can create
    more specialized accessor and constructor
    functions
  • As OOPLs became more popular in the mid 1980s, it
    was decided that CL needed something more
    powerful than structures and so CLOS was created
    and then added to the language

4
What Does CLOS Give You Then?
  • CLOS gives you the ability to utilize multiple
    inheritance
  • This might be considered a good thing by some,
    but overly complex by others
  • There is also an ability to control what gets
    inherited
  • Aside from these two things, CLOS is unlike other
    OOPLs for the following reasons
  • You can dynamically change an objects class
  • You can dynamically combine methods without
    access to source code
  • You can dispatch (invoke) based on either class
    or object identity
  • You can dispatch on multiple objects
  • You can provide user-defined code to determine
    method combination
  • Additionally, slots can contain data or code so
    that invoking a slot of an object carries out an
    action

5
All Types are Objects in CL
  • Ive been purposefully misleading to this point
    of the course
  • It turns out that all of the types that we have
    used to date (numbers, characters, strings,
    lists, etc) are objects
  • All objects inherit from T
  • One type of object is a standard class
  • Classes that you define will inherit from that
    class
  • The class (type) hierarchy is given below
    (Standard-Object and Structure-Object have
    numerous subclasses, omitted here)

6
CLOS Some Basics
  • You define classes using defclass
  • This is much like defstruct in that you supply
    the slots and various specifications for slots
  • e.g., default values, accessor functions
  • Classes may have 0 parents (in which case they
    default to inheriting from standard-object), 1
    parent, or multiple parents
  • You define methods using defmethod
  • Methods are not necessarily associated with any
    give class
  • Instead, methods are grouped together by common
    name where each method is unique in terms of the
    type(s) of parameter it expects
  • you either define a generic function for each
    group of methods, or it is generated
    automatically
  • Instead of message passing, a method is invoked
    by calling the generic function
  • the generic function selects which method(s) to
    then call
  • several methods may be called with one invocation
    this is where things get complicated!

7
Simple Example
(setf b1 (make-instance 'ball)) (setf (slot-value
b1 'color) 'red) (setf (slot-value b1 'type)
'medicine-ball) (setf (slot-value b1 'size)
10) (setf b2 (make-instance 'ball)) (setf
(slot-value b2 'color) 'orange) (setf (slot-value
b2 'type) 'basketball) (setf (slot-value b2
'size) 15)
(defclass ball ( ) (color type size)) (defmethod
getVolume ((b ball)) ( (/ 4 3) pi (cube
(slot-value b 'size)))) (defmethod
getSurfaceArea ((b ball)) ( 4 pi (square
(slot-value b 'size)))) (defmethod getWeight ((b
ball)) (let (weight-external weight-internal)
(if (or (equal (slot-value b 'type)
'medicine-ball) (equal (slot-value b
'type) 'filled)) (setf weight-internal 1)
(setf weight-internal 0)) (setf
weight-external ( (getSurfaceArea b))) (setf
weight-internal ( (getVolume b)
weight-internal)) ( weight-external
weight-internal)))
8
Defclass Explored
  • Defclass expects three things
  • The name of the class
  • The parent class(es) in parens empty parens if
    you want this class to have no parent
  • if no parent is specified, then the class has a
    default parent of Standard-Object (similar to
    inheriting from Object in java)
  • all slots are inherited from the parent(s)
  • methods defined on the parent(s) are also
    inherited, well talk about this later
  • multiple parents are allowed
  • the order that you place the parents will be used
    to break ties in cases where items (slots,
    methods) share the same name between parent
    classes
  • A list of slot names
  • as with structures, slot names can have a number
    of additional arguments such as default values,
    in which case you place the slot name and its
    arguments in an extra layer of ( )

9
Slot Arguments
  • Slots are not protected through information
    hiding
  • To enforce some information hiding, define
    accessors
  • Three types of accessor functions are reader,
    writer, and accessor (read or write)
  • to define accessor functions for a slot, you can
    state any or all of these
  • accessor name, reader name, writer name
  • Examples
  • (defclass ball ( ) (color (type reader
    ball-type) (size accessor ball-size)))
  • we can get b1s type by doing (ball-type b1)
  • or set b2s size by doing (setf (ball-size b2)
    12)
  • but we can only access color by (slot-value b1
    color)
  • Notice the accessor function does not preclude
    someone from using slot-value as in (setf
    (slot-value b2 ball-size) 0)
  • Therefore, while accessors give us a way to
    define an interface, no object is truly ever
    protected since we can always use slot-value!

10
More Slot Arguments
  • You can also define default values and default
    constructors for any slot
  • Default Initialization initarg symbol
  • this allows the caller to place symbol value in
    the make-instance instruction so that the slot
    will be provided an initial value
  • usually you will use the slot-name as the symbol
    with the name preceded by a as in color or
    size
  • Construction Initialization initform expression
  • this provides a default value for the slot,
    expression will be evaluated at the time the
    object is instantiated through make-instance
  • if expression is a function call, the function
    gets invoked and its return value is used to
    initialize the slot
  • expression will be evaluated only if an initarg
    does not exist, or was not supplied in the
    make-instance statement
  • note that the constructor is only for the slot,
    not for the entire object
  • Example
  • (defclass ball ( ) ((color initarg color) (type
    reader ball-type initform (input-ball-type))
    (size accessor ball-size)))

11
Methods An Introduction
  • The complexity of CLOS lies in the ability to
    create a variety of same-named methods
  • we will start however with simple methods
  • Use defmethod to define a method
  • (defmethod name (params) body)
  • The main difference between a method and a
    function is that at least one parameter must
    include the type of object that the method is
    defined for
  • assume our ball includes slots to store the ltx,
    y, zgt coordinates
  • the following method might be used to define how
    high a ball can be bounced

Notice how one parameter includes a type (ball)
but not all parameters must have them
(defmethod bounce ((b ball) hardness) (let
((btype (ball-type b))) (when (or
(equal btype basketball) (equal btype
tennisball)) (setf (slot-value b z) (
hardness (slot-value b z))))))
12
A Constructor Function
  • Lets create a method to construct a ball object
    for us
  • What should the constructor do?
  • initialize the slots
  • Which slots?
  • at least the type and size, the initial x, y, z
    coordinates may be unknown, so we can use
    optional parameters

(defmethod construct-ball ((b ball) type size
optional x y z) (setf (slot-value b 'type)
type) (setf (slot-value b 'size) size) (if z
(progn (setf (slot-value b 'x) x) (setf
(slot-value b 'y) y) (setf (slot-value b 'z)
z)) (progn (setf (slot-value b 'x)
'unknown) (setf (slot-value b 'y)
'unknown) (setf (slot-value b 'z) 'unknown))))
Notice that if z is unknown we change all
coordinates to be unknown If the ball class
would normally default x, y and z to 0, as we
might hope, then this constructor method changes
those default values, probably inappropriately
13
An Alternative Constructor
  • CLOS does not automatically call a constructor
    like in Java when you use new
  • so if you want a constructor to execute, you must
    invoke it explicitly
  • In the previous version, we already had a ball,
    and then we would invoke its constructor by
    calling (construct-ball myball )
  • here, we have a constructor function (not a
    method) that creates a ball and sets up its slot
    values

(defun construct-ball (type size optional x y
z) (let ((temp (make-instance
'ball))) (setf (slot-value temp 'type)
type) (setf (slot-value temp 'size) size) (if z
(progn (setf (slot-value temp 'x) x) (setf
(slot-value temp 'y) y) (setf (slot-value temp
'z) z)) (progn (setf (slot-value temp 'x)
'unknown) (setf (slot-value temp 'y)
'unknown) (setf (slot-value temp 'z)
'unknown))) temp))
Of the two approaches, neither is really
similar to Javas constructor
14
More on Method Parameters
  • When writing a method, at least one of the
    parameters must be specialized that is, listed
    with its type
  • The type specialization is what makes a method
    unique
  • Other parameters may or may not be specialized
  • in the previous example, hardness is not
    specialized and so could take on any type
  • Consider a situation where you have two sets of
    classes
  • an item to bounce, and a person
  • you may want a method based on a type of ball, or
    a type of person, or both
  • below, we have such a case based on whether the
    item being bounced is a ball or brick and whether
    the person is an athlete, a normal person, or
    other

Notice that with two specialized parameters, the
method is no longer defined for a single class
(defmethod bounce ((b ball) (p athlete) hardness)
) (defmethod bounce ((b ball) (p person)
hardness) ) (defmethod bounce ((b brick) p
hardness) )
15
Example
(defclass ball ( ) ((type accessor ball-type
initarg type) (size accessor ball-size
initarg size) (x accessor ball-x initarg x
initform 0) (y accessor ball-y initarg y
initform 0) (z accessor ball-z initarg z
initform 0))) (defclass brick ( ) ((x
accessor brick-x initarg x initform 0) (y
accessor brick-y initarg y initform 0) (z
accessor brick-z initarg z initform
0))) (defclass person ( ) ((type accessor
person-type initarg type) (size accessor
person-size initarg size))) (defclass athlete
(person) ((sport accessor athlete-sport
initarg sport)))
16
Example Continued
(defmethod bounce ((b ball) (p athlete)
hardness) (cond ((equal (ball-type b)
(athlete-sport p)) (setf (ball-z b) (
(ball-z b) hardness))) (t (setf (ball-z b) (
(ball-z b) .5 hardness))))) (defmethod bounce
((b ball) (p person) hardness) (setf (ball-z b)
( (ball-z b) .3 hardness))) (defmethod bounce
((b brick) (p athlete) hardness) (setf (brick-z
b) ( (brick-z b) .1 hardness))) (defmethod
bounce ((b brick) (p person) hardness) (setf
(brick-z b) 0))
Here, how high something bounces is based not
only on the type of thing (ball vs. brick) but
also based on whether the person bouncing it is
an average person or an athlete
17
With-Slots
  • Using the accessor function simplifies how to
    access slot values, but can still be cumbersome
  • A short-cut function is with-slots
  • Form
  • (with-slots (slots) object body)
  • Examples

(defmethod increase-size ((b ball) new-size)
(with-slots (size x y z) b (setf x ( x
new-size)) (setf y ( y new-size)) (setf z ( z
new-size)) (setf size new-size))) (defmethod
foobar ((a aclass) (b aclass)) (with-slots
(x y) a (with-slots (z) b (print
(list x y (slot-value a z)) (print
(list (slot-value b x) (slot-value b y) z)))))
18
Two Utility Functions
  • type-of provide it any datum and it returns the
    most specific type
  • alternatively, you can use class-of
  • If you do (class-of (class-of obj)) you get objs
    class parent class
  • find-class when passed the class name (as a
    symbol), returns the actual class
  • this is a pointer to the class definition, which
    itself is an object
  • you could combine this with describe, for
    instance, to see a description of the class as in
    (describe (find-class ball))
  • notice this is different from using describe on
    an instance, this enumerates the elements of the
    class itself (which contains things that you may
    or may not care to see)

gt (find-class 'ball) ltSTANDARD-CLASS BALL
2168C454gt
19
Some Notes on Objects
  • Recall that in CL, all types are actually
    objects, including structs
  • Here are some restrictions on types of objects
  • For built-in-classes (string, number, character,
    etc)
  • you may not use make-instance
  • you may not use slot-value
  • you may not use defclass to modify
  • you may not create subclasses
  • For structure-classes (that is, classes created
    through defstruct)
  • you may not use make-instance
  • it might work with slot-value (implementation-depe
    ndent)
  • use defstruct to subclass application structure
    types
  • consequences of modifying an existing
    structure-class are undefined full recompilation
    may be necessary
  • For standard-classes (defined through defclass)
  • none of the above restrictions apply

20
Example Shapes
(defclass shape ( ) ((x accessor shape-x
initarg x) (y accessor shape-y initarg y)))
(defmethod move-to ((figure shape) new-x new-y)
(setf (shape-x figure) new-x) (setf (shape-y
figure) new-y)) (defmethod r-move-to ((figure
shape) delta-x delta-y) (setf (shape-x figure)
( delta-x (shape-x figure))) (setf (shape-y
figure) ( delta-y (shape-y figure))))
(defmethod draw ((figure shape))) (defclass
circle (shape) ((radius accessor circle-radius
initarg radius))) (defmethod draw ((figure
circle)) (format t "Drawing a Circle
at(a,a), radius a" (shape-x figure)
(shape-y figure) (circle-radius figure)))
(defmethod set-radius ((figure circle)
new-radius) (setf (circle-radius figure)
new-radius))
21
Example Continued
(defclass rectangle (shape) ((width accessor
rectangle-width initarg width) (height
accessor rectangle-height initarg height)))
(defmethod draw ((figure rectangle)) (format
t "Drawing a Rectangle at(a,a), width a,
height a" (shape-x figure) (shape-y figure)
(rectangle-width figure) (rectangle-height
figure))) (defmethod set-width ((figure
rectangle) new-width) (setf (rectangle-width
figure) new-width)) (defmethod set-height
((figure rectangle) new-height) (setf
(rectangle-height figure) new-height)) (defun
polymorph( ) (let ((scribble) (a-rectangle)))
(setf scribble (list (make-instance 'rectangle
x 10 y 20 width 5 height 6)
(make-instance 'circle x 15 y 25 radius
8))) (dolist (a-shape scribble) (draw a-shape)
(r-move-to a-shape 100 100) (draw a-shape))
(setf a-rectangle (make-instance 'rectangle x
0 y 0 width 15 height 15)) (set-width
a-rectangle 30) (draw a-rectangle))
22
Generic Functions vs. Methods
  • When you define a method whose name had not
    previously been defined, CLOS automatically
    generates for a you a corresponding generic
    function
  • The generic function is used for bookkeeping in
    CLOS
  • it determines what method(s) to invoke when there
    is a method call
  • You may also write your own generic functions
  • (defgeneric name (params) documentation )
  • the generic function requires a name and list of
    unspecialized parameters
  • unlike the defmethod in which at least one
    parameter must be specialized
  • there is no body to the generic function
  • CLOS sets up a table for the generic function
    once it has been defined
  • as new methods that use the same name are
    defined, they are added to the appropriate
    generic functions table by listing, for a
    specialized parameter list, what method(s) are
    invoked
  • The generic function is necessary for any methods
    but you do not have to bother with defining one
    yourself

23
Example
  • From our shape example, when we first define the
    draw method, the following generic function was
    generated
  • (defgeneric draw (figure) documentation )
  • the generic function draw, had one entry at this
    point, ((figure shape)) would invoke that first
    defined defmethod
  • As other draw defmethods were defined, the
    generic function was added to
  • draw ((figure circle)) call the second
    definition
  • draw ((figure rectangle)) call the third
    definition
  • The generic function is consulted every time the
    method is called to determine which specific
    definition should be invoked
  • this is how polymorphism is implemented
  • what if there is no specific defmethod defined
    for this class?
  • then the generic function finds the closest
    matching definition by moving up the class
    hierarchy until a class is found that has a
    definition
  • this gets more complicated when we take into
    account multiple inheritance

24
Inheritance
  • In CLOS, inheritance is all-inclusive the child
    class inherits all slots from the parent class
  • further, all methods defined on the parent class
    can be invoked by instances of the child class
  • the generic function selects the most specific
    definition, if none are defined for this class,
    then the parent class definitions are consulted
  • In order to override inheritance
  • you must redefine things
  • you can redefine a slot although it will have
    the same name you can change its initform,
    initarg or accessor function
  • accessors are combined (new and old are unioned)
  • initargs are combined (new and old are unioned)
  • initforms are overridden
  • you can redefine a method by including this
    class name as the parameter specifier rather
    than the parent class

25
Multiple Inheritance
  • In order to create a class that inherits from
    multiple classes, you just list all of the
    parents
  • (defclass multiplechild (parent1 parent2 parent3)
    (( more specific slots go here if desired)))
  • When it comes to inheriting from multiple parents
  • slots are inherited from the left-most class
    first, and then each successive class to the
    right as long as slot names do not conflict
  • when there is conflict, then only the first slot
    of the same name is inherited
  • the same will be true of inheriting methods the
    generic function will select a method based on
    the left-to-right listing of each parent class
  • if none is found, then polymorphism kicks in and
    each grandparent is checked from left-to-right

26
Example
(defclass creature ( ) ((type accessor
creature-type initform 'unknown) (height
accessor creature-height initform 'unknown)
(weight accessor creature-weight initform
'unknown) (habitat accessor creature-habitat
initform 'unknown))) (defclass bird (creature)
((type initform 'bird) (habitat initform
'air))) (defclass mammal (creature) ((type
initform 'mammal) (habitat initform
'ground))) (defclass ostrich (mammal bird)
((type initform 'ostrich)))
(defmethod lives ((c creature)) (format t "A"
(creature-habitat c))) (defmethod lives ((b
bird)) (format t "I live in the
air")) (defmethod lives ((o ostrich)) (format t
"I am an ostrich")) (lives (make-instance
ostrich)) ? I am an ostrich (lives
(make-instance bird)) ? I live in the air
27
What About Multiple Specificiers?
  • Imagine that a method had two parameters, both of
    which were specialized?
  • Consider the following partial definitions for
    some method op2
  • (defmethod op2 ((x number) (y number)) ...)
    method 1
  • (defmethod op2 ((x integer) (y integer)) ...)
    method 2
  • (defmethod op2 ((x float) (y number)) ...)
    method 3
  • (defmethod op2 ((x number) (y float)) ...)
    method 4
  • Which version is called for each of the
    following?
  • (OP2 11 23) method 2
  • (OP2 13 2.9) method 4
  • (OP2 8.3 4/5) method 3
  • (OP2 5/8 11/3) method 1
  • In a left-to-right manner, each parameter is
    determined by following the hierarchy, so (OP2 13
    2.9) identifies methods with an integer first and
    then a float second (method 3 is the only one
    that fits integer first, but it does not have
    float second) so we try the parent class of
    integer (number)

28
Class Precedence List
  • In order for the generic function to know which
    method to invoke, every time a new defmethod
    statement is defined, the associated generic
    function consults its class precedence list for
    the specialized parameter(s)
  • the CPL is in essence the concatenation of all
    classes and their parents of the classes in the
    parameter list
  • consider the figure on the right showing the
    class hierarchical structure
  • C3 is a subclass of C1, C5 is a subclass of both
    C3 and C2, etc
  • The CPL is consulted for each parameter from left
    to right until a match is found for all parameters
  • Consider a method that accepts an instance of one
    of these classes, and a number
  • Imagine that we have a method defined with these
    specialized params
  • (C2 Integer)
  • (C2 Number)
  • (C3 Integer)
  • (C3 Number)
  • Which method is invoked if we call it with a C6
    and an integer? A C6 and a float?

29
Calling Multiple Methods
  • The strength of the generic function in CLOS is
    that multiple methods can be invoked when you
    call one
  • the generic function keeps track of the order by
    which to call functions
  • (call-next-method) is a function that allows a
    method to invoke the next one
  • if we had added (call-next-method) as the last
    thing that lives did for the ostrich class, then
  • lives of ostrich would print I am an ostrich
    and then
  • call lives of the mammal class since there is
    none, it would then
  • call lives of the bird class and we would get I
    live in the air
  • if we had also added (call-next-method) to the
    bird class, it would then call lives for the
    creature class and we would also get Ground
    output
  • Thus, call-next-method can, in a way, take the
    place of super( ) as used in Java to invoke the
    parent class method of the same name

30
Using Multiple Methods
  • Aside from using call-next-method, you can also
    create combinations of methods so that, when
    called, a group of methods, assembled by the
    generic function, will all be invoked, one at a
    time
  • to accomplish this, there are 3 specifiers that
    can be placed in a defmethod to denote when the
    method should be called
  • before, after, around
  • these dictate when this method should be called
  • if a method is available, it is called
  • if there is an additional method whose parameters
    match, and has before, then it is called first
  • if there is an additional method whose parameters
    match, and has after, it is called last
  • with these, if there are multiple methods whose
    parameters match, then the methods are called
    using the CPL like the previous example
  • if there is an additional method whose parameters
    match and has around, then this method, and only
    this method, is invoked
  • You can add call-next-method if you want an
    around method to invoke the next around method

31
Example
(defclass food ( ) ( )) (defmethod cook before
((f food)) (print "A food is about to be
cooked.")) (defmethod cook after ((f food))
(print "A food has been cooked.")) (defclass
pie (food) ((filling accessor pie-filling
initarg filling initform 'apple))) (defmethod
cook ((p pie)) (print "Cooking a pie.") (setf
(pie-filling p) (list 'cooked (pie-filling
p)))) (defmethod cook before ((p pie)) (print
"A pie is about to be cooked.")) (defmethod cook
after ((p pie)) (print "A pie has been
cooked.")) (setq pie-1 (make-instance 'pie
filling 'apple)) (cook pie-1) "A pie is about
to be cooked." "A food is about to be cooked."
"Cooking a pie." "A food has been cooked." "A
pie has been cooked." (cooked apple)
The return value is from the main method (in this
case, pies non-before/after version of cook)
32
Example Continued Using around
(defmethod cook around ((f food)) (print
"Begin around food.") (let ((result
(call-next-method))) (print "End around
food.") result)) (cook pie-1) "Begin around
food." "A pie is about to be cooked." "A food
is about to be cooked." "Cooking a pie." "A
food has been cooked." "A pie has been cooked."
"End around food." (cooked (cooked apple))
Here, the around method uses call-next-method so
that the before, main and after methods are also
invoked Without this however, notice what happens
(defmethod cook around ((f food)) (print
"Begin around food.") (print
"End around food.")) (cook pie-1) "Begin around
food" "End around food"
Why should (cooked ) appear twice?
33
Example
  • A (slightly) better example is presented here
  • We have an adventure game where the base class is
    a creature
  • creatures will have some way to attack and some
    way to defend, for now we will use three slots
    attack-points, life-points and defense-points
  • we define an attack method for creature which is
    passed another creature
  • if a random number generated by our creature gt
    the other creatures defense-points, then this
    creature generates a random number from 1 to
    attack-points and this is deducted from the other
    creatures life-points
  • We extend creature to a human class and a dragon
    class, which are extended into magician and
    magic-negating-dragon respectively
  • rather than redefining attack for these four
    subclasses, we can use some combination of
    before, after and around
  • for instance, if a human is able to perform two
    attacks, then a before method might invoke the
    parent method twice
  • the magic-negating-dragon might have an around
    method that checks to see if the attacking
    creature is using magic, if so, nothing happens,
    otherwise this method calls the next method to
    permit the attack

34
Specializing on an Instance
  • Just as parameters in a method specialize on
    classes, you can specialize parameters on
    specific instances as well
  • Form
  • (defmethod name ((var instance-name) params)
    body)
  • Example
  • (defmethod cook ((p my-pie)) (print "My pie is
    in the oven."))
  • This is of limited use since a programmer may not
    know what instances are going to be generated
  • Consider though an example where the system has a
    pre-defined object
  • if a method is called with any instance, one
    behavior might be desired, but if called with
    this system object, then another behavior is
    desirable
  • one of the texts gives an example of what happens
    when a customer overdraws on their bank account
    versus the bank president!

35
Code in Slots
  • Slots (whether from an object or a struct) just
    store what any other CL variable stores, a
    pointer
  • this can point to a number or symbol or list, but
    can also point to code
  • consider a macro that generates code and places
    that code into the slots of an object
  • now, an object-user can invoke the necessary code
    by doing (eval (slot-value obj slot-name))
  • or alternatively, if the function name itself has
    been placed into the slot rather than the
    function, you can do (funcall (slot-value obj
    slot-name) params)
  • In this way, you can use macros to generate code
  • And you can place that code inside of objects for
    encapsulation purposes
  • encapsulation here is not in the sense of ADTs
    but instead in the sense that an object, which is
    a problem solving agent, has code available
    internally

36
One Last Comment
  • Because of Common Lisps dynamic nature, CLOS has
    the ability to dynamically redefine classes and
    instances
  • if you redefine (or define for the first time)
    accessors (including readers and writers) then
    you can use them on an instance that was already
    created previously
  • if you redefine or add an initform or initarg, it
    has no affect on the previously defined instances
  • newly added slots are added to the instance
  • deleted slots are removed from the instance

(defclass foo ( ) ((a initform '1) (b initarg
b))) (setf f1 (make-instance 'foo b
2)) (describe f1) ltFOO 2069C6B4gt is a FOO A
1 B 2
(defclass foo ( ) ((a initform '3 accessor
get-a) b (c initform '4))) (describe f1) ltFOO
2069C6B4gt is a FOO A 1 B 2 C
4 (get-a f1) returns 1
Write a Comment
User Comments (0)
About PowerShow.com