class name Point super class Object instance var x y class var pi class messages and methods newX:xvalue Y:yvalue | | ^ self new x: xvalue y: yvalue newOrigin | | ^ self new x: 0 y: 0 initialize | | pi <- 3.14159 instance messages and methods x: xcoord y: ycoord | | x <- xcoord y <- ycoord moveDx: dx Dy: dy | | x <- dx + x y <- dy + y x | | ^x y | | ^y draw | | << code to draw point >>Suppose we execute the following code:
p <- Point newOrigin p moveDx: 3 Dy: 4What would be the values of
p x (3) p y (4)Run-time Structures for points
The (unoptimized) run-time structure for Points looks like:
Insert pictureNote that this picture is schematic; actual implementations might perform various optimizations to improve performance.
class name Colored Point super class Point instance var color class message and methods newX: xvalue Y:yvalue C:cvalue | | ^ self new x: xvalue y:yvalue color:cvalue instance messages and methods draw | | << draw color point >>Suppose we execute the following code:
cp <- ColoredPoint newX:1 Y:2 C:"red" cp moveDx: 3 Dy: 4What would be the values of
cp x (4) cp y (6)Run-time structure to support inheritance
The (unoptimized) run-time structures for colored points might look like:
insert picture here.Again, this picture is schematic. An actual compiler would probably perform a number of optimizations to improve performance. One such optimization is to cache recently found methods within a given class.
Consider for example a list of objects, some of which are points, others of which are colored points. If we wanted to display every point on the list, we could traverse the list, sending each object the draw method. Because of dynamic lookup, the point objects will execute the point draw method and the colored points will execute the colored point draw method. Dynamic lookup supports code re-use, since one routine will display lists of points, lists of colored points, and lists that have both points and colored points.
The run-time structures above support dynamic lookup in two ways.
A type B is a subtype of a type C if any context expecting an expression of type C may take any expression of type B without introducing a type error.we can see that subtyping is about substitutivity: when may we safely replace one object with another without introducing an error? This notion makes sense for Smalltalk, even in the absence of types. In Smalltalk, we say that one object ob1 conforms to another ob2 if no context expecting ob2 will produce a new error if given ob1 instead.
What must be true about ob1 and ob2 for this relationship to hold between them?
Is there any necessary relationship between the classes that created ob1 and ob2?
Why does this make sense in general?
When would this relationship not hold?
ob <= mwe can determine statically which slot in ob's vtable (method dictionary) the method m lives, so method lookup can be done in constant time in C++.
The pseudo-variable super is similar, except that when a message is sent to super , the search for the appropriate method body starts with the object's parent class, instead of the object's class. This mechanism provides a way of accessing a parent class's version of a method that has been overidden in a subclass class.
2. Classes: object definitions. At run-time, store pointers to templates, method dictionaries, and parent classes.
3. Inheritance: one class's definition may cite another class C as a superclass, in which case the derived class inherits the instance variables and methods of the class C. Methods that are present in the parent class may be redefined in the derived class.
4. Subtyping: Conformance relation. Depends on messages understood, but not underlying representations or inheritance hierarchy.
5. Encapsulation: protected instance variables public methods.