CS212 Notes for Lecture 12

March 2, 2000

Outline for the day:


This material is covered in the handout on object-oriented
programming. See the handout for examples and Swindle syntax.

IDEA:

Have a CLASS HIERARCHY which specifies the relation between types.

CLASS = a collection of similar objects, elg.
"Animal", "Bird", "Dinosaur", ...

INHERITANCE - inherit state and operations

"A duck is a kind of bird" --ducks have all properties that birds have, and then some

Subclasses may have more or different operations:

 <thing>
    |
 <animal>
    |
<dinosaur>

MANTRA:

An object of a subclass can be used ANYWHERE that an object of a superclass can be used.


There are two metaphors of OOP:

"Fly south for the winter!"

(send big-bird 'fly 'south)

(fly big-bird 'south)

There's still debate on which is "better"

We use GENERIC FUNCTIONS because they fit Scheme better, and they support multimethods, which are useful.


Some Terminology:

CLASS = specification of a collection of similar objects

"Dinosaur"

INSTANCE = An individual object (entity) of some class.

"Dino", "Barney"

METHOD = Code that operates on specific classes. A function.

A Class definition consists of several things:

A class is defined with respect to its SUPERCLASSES:

A class will often have more information than its superclasses

- So two dinosaurs can have different favorite songs!

Superclasses can be direct or indirect.

DIRECT -- immediate parents in the hierarchy listed with the class creation

'animal' is a direct superclass of 'dinosaur'

INDIRECT -- superclass of a direct superclass.

'thing' is an indirect superclass of 'dinosaur'

A class inherits slots from all its superclasses, both direct and indirect, thus it has

e.g.:

thing - location

animal - size, weight

dinosaur - songs

A dinosaur will have location, size and weight slots as well as songs.


In Swindle the special form defclass is used to define a class

(defclass <classname> (<super1> ... <supern>) slot1 ... slotm)

where

A slot must contain at least a slot name.

More than one direct superclass mean that this class inherits from several direct superclasses.  T this is called multiple inheritance. If each class has just one direct superclass, it is single inheritance. In this case the hierarchy forms a tree (each class has one parent). Java only supports single inheritance.

If the list of superclasses is empty, the class is directly under <top>.

Besides a slot name, a slot can contain numerous other specifications, including:

:type the type of the slot, defaults to <top>

:initarg how to initialize this slot in a call to make

:initvalue default value in case no init keyword given to make

(defclass <animate> ()
  (weight :type <number> :initarg :size :initvalue 10)
  (hunger :type <number> :initarg :hunger
                  :initvalue 0 :accessor hunger))

(defclass <dog> (<animate>)
  (name :type <symbol> :initarg :name :accessor name))

CONVENTIONS:

To make instances,

(make class-name keyword1: v1 keyword2: v2)
(define bismarck (make <dog> :name 'Bismarck))

A useful procedure is (instance-of? object class), which returns true if the given object is of the specified class.

Example:

(instance-of? bismarck <dog>) ==> #t
(instance-of? bismarck <animate>) ==> #t

Each instance has slots to store information. Each slot has a name which it was given by the defclass form.

Example:

(name bismarck) ==> Bismarck
(slot-ref bismarck 'weight) ==> 10 [why?]
(slot-set! bismarck 'weight 20)

We can use set! to change the value of a slot in an instance (note that this requires that you define an accessor).

(set! (name bismarck) 'Otto)

ALTERNATIVE SYNTAX:

(set-name! bismarck 'Otto)

Example:

(define bismarck (make <dog> :name 'Bismarck))
(define otto (make <dog> :name 'Otto))
(set-name! bismarck 'Otto)
(set-name! otto 'Bismarck)
(let ((bingo bismarck))
      (set! bismarck otto)
      (set! otto bingo))

OPERATIONS:

(defmethod eat ((me <animate>) (food <symbol>))
  (cond ((member food '(salad fruit tofu))
         (set! (hunger me) (- (hunger me) 1)))
        ;; CS212 is not a class in nutrition
        ((member food '(donut chips))
         (set! (hunger me) (- (hunger me) 2)))))

(defmethod eat ((me <dog>) (food <symbol>))
  (let ((last-hunger (hunger me)))
    (call-next-method)
    (cond ((>= (hunger me) last-hunger)
           (print (name me))
           (print " is hungry. Feed me!")))))

Note: the second function here has the access to the instance variables of <dog> (NAME) and of its superclass <animate> (HUNGER in this case). Why? Because of the type of the parameter. Can�t generally assume that something of type <animate> has the slots of a <dog>.

Now, we can do:

(eat bismarck 'dry-bone)

The generic function eat uses the class hierarchy to find the most specific method that applies

There is a method for instances of class <dog>, and bismarck is an instance of that class, so that method is applied. (This is the same mechanism that we saw for generic function operating on values in general).

If there had been no method for <dog>, we'd try <animate>, which is the direct superclass (and so on up the hierarchy)

NOTE:

So, the second function gets invoked because <dog> is more specific than <animate> with respect to the given argument, bismarck (which is of class <dog>). This function binds a local variable and then calls the function call-next-method --- which is a special function that means "run whatever method would have run if the method currently running had not been part of the generic function".

In this case, that means call the function with parameter of type <animate> (as <animate> is the closest superclass of <dog>). This function checks whether dry-bone relieves hunger, it does not, so it just returns. Then the method for class <dog> continues running (the call-next-method has returned), and as the hunger value has not decreased, prints out:

Bismarck is hungry. Feed me!

We will cover next-method more in the next few lectures, so if it does not make total sense at the moment, don't worry. At least this simple example should make sense.

Thus, note that with classes and methods we can either replace functionality (a <dog> method that is special and does something totally different than the <animate> method) or we can do something slightly different (using call-next-method to do what would have happened, before or after doing something else).


Summary:

Methods are type-specific operations (functions) which generic functions call - The generic function 'fly' might have methods for <bird> and <airplane> and <penguin>


CS Joke of the day:

[Xerox PARC (Palo Alto Research Center) is the research arm of Xerox Corp, where they invented the personal computer, the graphical user interface, the local area network, and the copying machine. ]

Q: What's the difference between Jurassic Park and Xerox PARC?

A: One's a high-tech theme park for dinosaurs. The other's a movie by Steven Spielberg.