12.1 Object-Oriented Paradigm
This is a very natural style of programming, objects ``know'' themselves and can report this knowledge to anyone who asks them. Here is an example of a Point object.
class Point {
private int x;
private int y;
// constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
// tell the world what the x coordinate value is
public int Xcoord() {
return x;
}
// tell the world what the y coordinate value is
public int Ycoord() {
return y;
}
// move the point to new coordinates
public void move(int newx, int newy) {
x = newx;
y = newy;
}
}
1960s
1970s
Smalltalk
1980s
C++
1990s
Java, OOScheme, OOCOBOL, etc.
The popularity of imperative languages is giving way to that of OO
languages, but this is
somewhat illusory since most OO languages are imperative, but considered
part of the OO
paradigm (which we will study shortly) due to their extra encapsulation.
12.2 Case Study - Smalltalk
History
12.2.1 Objects and Classes
Smalltalk has a rich variaty of predefined object classes, many of which are
named in section 12.2.5.
Expressions
--E.g. Integer class has operations such as +, -, *, // (interger division), 'squared', 'even', ' gcd:' etc.
--m' even is evaluate the integer m's evenness resulting a Boolean object.
--m gcd: n requests m to return the greatest common divisor of m and n.
The result is another Integer object
--m + n requests m to return the sum of the m and n.
In general we have the following syntax for expressions
For Example:
// E0I
n squared
n asFloat
// variables hold reference to object
x <- 3. // now x points to the integer object 3
// Eo I E1
n * 4
m >= n
// x is an array object with three values
x <- #(0, 0, 0).
// what is at x[3]?
x at: 3.
// do at:put: method on array with args 2,3
// x[2] = 3.
x at: 2 put: 3.
// note, array could be heterogeneous
x at: 2 put: "hello there".
// assignment shares the reference between vars
y <- x.
x at: 1 put: 3 // changes value in y!
m between: 1 and: n-1
-Each of these classes provides a set of operations.
Suppose that a is an Array
a at: n requests a to return the object that is its nth component
a at: n put: x requests update a' nth value to object x.
monthsize <- #(31 28 31 30 31 30 31 31 30 31 30 31) ... monthsize at: 2 put 29
A primitive operation such as '+' will check its argument object's tag to ensure that its class is acceptable. Such check is effectively dynamic type checks
eg. in a graphics program, a picture might be represented by a Set object whose components are points, circles and lines.
Side effect example: form V <- E result V refers to E's object
n <- n-m //n reference to the object expression n-m m <- n // m and n reference the same object nowThis dangerous for composition objects. Suppose that a refer to an Array object. Then:
b <- a.
a at: i put: x //makes b refer to the same Array object
// updates on component of the shared object
Control (Commands )
Smalltalk has no built-in control structures, but conditional and iterative control structures are embedded within the framework.
// the block is the entity enclosed in brackets
counter <- [ n <- n + 1 ] .
// block is called as follows
counter value:
// this changes the object that n references
// to the previous object + 1
// calling the block also returns whatever
// object is created by the block
// one presumes the last object created
x <- counter value:
// this changes the object that x references
// to the object n + 1, and also changes what
// n references (a side-effect of evaluating
// the block)
Example:
//the block is the entity enclosed in brackets
increment <- [ :i | i + 1 ] .
// block is called as follows
increment value: x
// this changes the object that x references
// to the previous object + 1
--- if-then-else - methods on boolean object using block objects as arguments
// pass ifTrue: ifFalse: message with arguments //[m/n], [0] to the receiver (an object) that is // the result of evaluating n > 0 it will either // be the object 'true', or the object 'false' n > 0 ifTrue: [ m / n ] ifFalse: [0]while loop example
m <- 0.
[ n > 0 ] whileTrue: [ n <- n / 2. m <- m + 1 ]
Example Point class - just the methods shown, assume x and y are hidden variables
int class
placeat: xnew and: ynew
x <- xnew. y <- ynew
move: xnew and: ynew
x <- xnew. y <- ynew
xcoord:
^x
// means return the object that x points to
//(dereference x)
ycoord:
^y
moveby: xshift and: yshift
x <- x + xshift. y <- y + yshift
draw: .... //code to draw the Point
endclass
placeat: xnew and: ynew radius: rnew
x <- xnew. y <- ynew. r <- radius
draw: .... //code to draw the Circle
So we would create new points and circles as follows.
// set up an array with two slots
image <- #(0, 0)
// put a point object in the first array position
image at: 1 put: Point::placeat: 3 and: 4.
// put a circle object in the first array position
image at: 2 put: Circle::placeat: 100 and: 7 radius: 5.
// iterate throughout the array drawing each object
m <- 2.
[ m > 0 ] whileTrue: [ x <- image at: m. x draw: ]
// note the dynamic binding, which draw: to execute
//depends upon object class x belongs to, but the
//same loop will work for object class not yet
// created!
Inheritance
Object ------is superclass
|
--------------------------------------------------
| | | | |
UndefinedObject | Boolean | Collection
| File |
Magnitude --------------
| | | |
--------- Bag Set SequenceableCollection
| | | | |
Character Number Dictionary LinkedList ArrayedCollection
| | |
-------- String Array
| |
Integer Float
Case Study -Java
public class Point {
protected int x, y; // coordinates of the Point
// no-argument constructor
public Point() { setPoint( 0, 0 ); }
// constructor
public Point( int a, int b ) { setPoint( a, b ); }
// Set x and y coordinates of Point
public void setPoint( int a, int b )
{
x = a;
y = b;
}
// get x coordinate
public int getX() { return x; }
// get y coordinate
public int getY() { return y; }
// conver the point into a String representation
public String toString()
{ return "[" + x + ", " + y + "]"; }
}
public class Circle extends Point { // inherits from Point
protected double radius;
// no-argument constructor
public Circle()
{
// implicit call to superclass constructor
setRadius( 0 );
}
// Constructor
public Circle( double r, int a, int b )
{
super( a, b ); // call the superclass constructor
setRadius( r );
}
// Set radius of Circle
public void setRadius( double r )
{ radius = ( r >= 0.0 ? r : 0.0 ); }
// Get radius of Circle
public double getRadius() { return radius; }
// Calculate area of Circle
public double area()
{ return Math.PI * radius * radius; }
// convert the Circle to a String
public String toString()
{
return "Centre = " + super.toString() +
"; Radius = " + radius;
}
}