Chapter 12

handprintΛογισμικό & κατασκευή λογ/κού

18 Νοε 2013 (πριν από 3 χρόνια και 8 μήνες)

110 εμφανίσεις

Oriented Programming

Objects were first introduced in Simula 67

although the intent in Simula was not to provide a new programming
paradigm, but instead to offer a construct to easily build models for
simulation purposes

OOP was developed fully in Smalltalk

the object can be thought of as an extension to ADTs except that the
structure can be extended for easy modification leading to a hierarchically

passing was implemented rather than function calls

encapsulation was enforced through the class construct

different types of objects call upon the same method if the objects were related
hierarchically, leading to polymorphism and generic methods

OOPL was later included in many languages

C++ (a descendent of C with many of Smalltalk’s class ideas)

Common Lisp (added to CL was CLOS, the Common Lisp Object System)

Ada 95 (Ada 83 + objects)

Java and C# introduce a newer generation of OOPLs related to C++ but
cleaner and easier to understand

Scripting languages started adding objects with JavaScript and has continued
with both Python and Ruby (Ruby is the only
OOPL since Smalltalk)

OOPL Definitions

Pure OOP: all computation done by message passing

Hybrid OOP: computation shared between message passing and
function calls

most OOPLs are hybrids (C++, Ada 95, Delphi, Common Lisp, C#)

Java would be pure if not for the 8 primitive types

Inheritance: to solve the modification problem; controls what
definitions a subclass obtains from a parent class

to control inheritance, the language might include modifiers such as

question: can a subclass override a parent’s definition?

if so, can the parent item still be accessed or is it hidden?

question: is multiple inheritance available? (C++ and CLOS have this)

Polymorphism: variables that can reference any subclass of a given

we need a mechanism to bind a message to the proper method, which is often
done at run time so is called
dynamic type binding

Class/Subclass Relationships

Aside from C++ and Common Lisp, classes in other
languages must have one (and only one) parent

any defined class needs a parent, what is that parent’s parent?

with this restriction, such languages will offer a starting class

usually called Object

what if a parent class is not specific enough to have an
implementation for its methods but all child classes should
have the given methods?

in this case, we can make the methods in the parent class
known as

this forms what is known as an
in Java

an interface means that the pre
specified abstract methods
implemented in any class that implements (inherits from) the interface

classes with abstract entities cannot themselves be instantiated, but can
be extended into subclasses

Design Issues

Exclusitivity of Objects

are all types classes, or are there other types?

dictates whether all communication is via message passing or if other
forms are provided and whether the language is pure OOP or hybrid

Subclass relationships

is a subclass a descendant of the class (


or some different relationship such as a subrange or subset

Inheritance and information hiding

how are these provided? is information hiding enforced?

Type checking and polymorphism

is type checking done and if so, when?

can variables be polymorphic?

Single vs. multiple inheritance

which is allowed?

Allocation and Deallocation of Objects

when and how is this performed?

Note: we will explore

sample programs from

many of the languages

discussed here on

so this set of notes largely

omits specific examples


Programs consist only of objects and messages

variables are local (private) or global (shared)

all vars are pointed to by ptrs


single inheritance only, subclasses inherit everything from the parent

class methods/data

can be overridden in the derived class

the parent’s methods/data are only hidden but still accessible (using super)

Dynamic binding for polymorphism

when a method is called, a search takes place at the child’s
location for that method’s definition

if not found, the search continues up the hierarchy until the
method’s definition is found (if none found, error)

if parameters and return type are the same for all classes that a
polymorphic variable can take on, then type checking can be done at
compile time, otherwise it is done at run

Smalltalk Messages and Methods

All items in Smalltalk are objects, so all
operations are methods and specifying actions is
done strictly through message passing (even if it
doesn’t look like it!)

messages contain

object for whom the message is sent

method to invoke

any needed parameters

some examples:

21 + 2

// object 21 receives message + and parameter 2

sum / count //sum receives message to divide by count

firstArray at: 1 put: 5 // firstArray gets message at with

// parameter 1 and put 5, or

// firstArray[1] = 5;

ourPen home; up; goto: 500@500; down; home

graphics routine with multiple messages passed to ourPen

Message Types Continued

3 forms of methods:

unary methods (message without params)

binary methods (as with 21 + 2 or sum / count,
mostly used for arithmetic operations)

and the general form shown below where key# is a
keyword for the object

key1: param1 key2: param2 … key n: param n

Assignments statements operate as follows

any message expression, variable or literal object on

LHS is a data instance




deducts grossPay: 350.0 dependents: 4

Defining a Class

Much like Java, you define your class, its variables
and its methods

In Smalltalk, you have class variables and instance

class variables are like Java’s static instance variables

that is,
you define a variable to be

The notation is:

Object subclass: #

: ‘’

: ‘’

: ‘’

Category: ‘

If you have variables to define in any section, separate
them by spaces within the ‘’ as in ‘x y z’


contains variables that are not owned by
this class, so you can use this to define global variables that this
class might manipulate

bad idea of course!

Defining Methods

Since Smalltalk is interpreted, you typically define
your methods interactively
you have defined
your class rather than wrap them up in a single

Methods by default do not expect to receive parameters

If you want your method to receive a single parameter,
add :

after the method’s name as in


If you have multiple parameters, you must have specific
keywords for all but the first as in

: val1 Value2: val2 Value3: val3

In this case, you would call the method as
: 5 Value2: 3
Value3: 10

Local variables are declared in | | notation as in | x y z |

To return a value at the end, use ^

Example: Point

Object subclass: #NameOfSubclass

instanceVariableNames: ‘p1 p2'

classVariableNames: ''

poolDictionaries: ''

category: 'Point‘





init: x second: y



distance: point2

| temp1 temp2 |


point2 getP1)*(p1

point2 getP1).


point2 getP2)*(p2

point2 getP2).

^ (temp1

temp2) sqrt.

Here is how we can interact with Points:

point1 := Point new.

point1 init: 5 second :10.

point2 := Point new.

point2 init: 12 second :7.

point1 distance: point2.

Blocks and Control Structures

Blocks are specified in [ ] with instructions separated by .’s

block code is only executed when the message
is sent to the block


[sum <

sum + index]

addIndex value

value is a message to addIndex to execute the block

Blocks can contain relational expressions and return True or
False providing a mechanism for conditional blocks

conditional blocks can be used to form a pretest loop method called


1. sum

0. [x <=20]

whileTrue: [sum

sum+x. x


another loop is timesRepeat: which is provided an integer value

Selection statements use ifTrue and ifFalse as in

[x > 0] ifTrue: [y

x + 1. x


1] ifFalse: [y


Evaluation of Smalltalk

Small language, simple (?) syntax

mathematically limited

less efficient than imperative languages

because of dynamic type checking, errors often not caught until run

First real OOPL and the only pure OOPL until Ruby

successor languages did not like to force everything to be message passing
and therefore most OOPLs are hybrids of some form

Smalltalk pioneered many of the ideas found common in all

LOGO was a system built using Smalltalk to provide a graphical
programming environment

objects are windows, menus, cursor, lines, …

messages include down, up, turn:degrees, go:distance, goto: point, home,
north, …

Pen is the general class designated to draw

To draw a triangle:


Pen new defaultNib: 2.

OurPen up; goto: 800@300; down

OurPen go: 100; turn: 120; go: 100; turn: 120; go: 100


Based on C (same types) but adds classes

updates Smalltalk’s object system as follows:

classes can either be a derived class (from a superclass) or stand alone
without having a superclass

some or all data and functions can be inherited from base class(es)

objects can be either stack dynamic or heap dynamic (these require a
destructor method to deallocate memory)

both forms require a constructor

whereas Smalltalk’s use of classes was consistent and fairly
simple (because the language itself was small), C++’s use of
classes is very complex and the language is quite large

C++ is the most used OOPL in spite of (or maybe
because of) having complex object
oriented mechanisms

such as multiple inheritance and complete flexibility in
controlling what is inherited

Controlling Inheritance

Class members can be
private, protected or

private members are only
accessible by member
functions and friends of
the class

friends are
explicitly declared as
friends by the given class

public members are
accessible by any function

protected members are
like private members
except that derived classes
can modify access rights
for inheriting members

class base_class {


int a; float x;


int b; float y;


int c; float z; }

class sub1 : public base_class {…};

class sub2 : private base_class {…};

in sub1: b and y are protected, c and z are public

in sub2: b, y, c and z are private and no derived

class of sub2 will have access to any of these

a and x are not accessible to sub1 or sub2

note that since sub2 is a derived private class, no member
of the parent class is explicitly visible, and so b, c, y and z
must be re
exported to be used in an instance of sub2

this is done using : : as in base_class : : c;


class single_linked_list {

class node {

friend class single_linked_list;


node *link;

int contents;



single_linked_list( ) {head = 0};

void inset_at_head(int);

void insert_at_tail(int);

int remove_at_head( );

int empty( );


class stack : public single_linked_list {


stack( ) { }

void push(int value) {


(int value);


int pop( ) {

single_linked_list::remove_at_head( );



class queue : public single_linked_list {


queue( ) { }

void enqueue(int value) {


(int value);


int dequeue( ) {

single_linked_list::remove_at_head( );



The nested inner class, node, lists

single_linked_list as a friend so that

single_linked_list can access node’s private parts

Both stack and queue extend

single_linked_list but both are public

derivations, we should restrict that by

making them private

see the code on

Page 540

C++ Object Binding

Objects can be referenced through ordinary variables

these objects are stack dynamic and all method calls would be
statically bound

Otherwise, objects are referenced via pointers

these objects are heap dynamic

any pointer of a class can point at any derived class of that

thus, pointers can be polymorphic variables

but non
pointers cannot

if the variable is polymorphic then method calls are
dynamically bound

any method that will be dynamically bound must be declared
as a


public class shape {


virtual void draw( ) = 0; // indicates that draw is a pure virtual function


// that is, that there is no implementation here

// so shape is an


public class circle : public shape {


virtual void draw( ) {…}


public class rectangle : public shape {


virtual void draw( ) {…}


public class square : public rectangle {


virtual void draw( ) {…}


square s;

// s is dynamically

rectangle r; // bound to draw

shape &ref_shape = s;

ref_shape.draw( );

// whereas r is statically

r.draw( );

// bound to draw


Most of you are familiar with Java, so we will only cover a few highlights of
objects in Java

all entities in Java are objects except for the primitive types so all Java
programs require class definitions

the class with the main method is an object that creates or calls upon all other

Java restricts inheritance to single inheritance

all objects must have a parent (no stand
alone objects), by default, the parent is

multiple inheritance can somewhat be simulated through interfaces

all objects are heap dynamic and pointed to by reference variables (a
pointer that does not require dereferencing)

all method calls are dynamically bound (unless a class is denoted as final
which means it can not be extended, so it will not have subclasses)

Java includes a finalize method that will be invoked before the object’s
memory is returned to the heap

Java has no destructor since garbage collection is used

Java is simpler and less powerful than C++

but that might be a good thing!


C# offers constructs for the class (similar to Java) and
struct (similar to C++)

structs are stack dynamic, objects are heap dynamic

C#’s syntax is more like C++ for class definitions, for

public class NewClass : ParentClass {…}

dynamic binding is done only if methods are specially
indicated as
where overridden methods in derived
classes must be specially indicated through the word

classes that contain abstract methods must be declared as abstract and
abstract classes cannot be instantiated (see page 534 for example)

like Java, C# offers only single inheritance and all classes
must have a parent (no stand
alone classes) with the parent
class defaulting to Object

the Object class implements ToString, Finalize and Equals, which are
inherited to all classes

Objects in Ada 95

Ada 83 included the Package for encapsulating ADTs

Objects were added for Ada 95 as an extension for this

Objects became a new type called a

Tagged types are either records or private types

private types are true objects as they offer information hiding

Packages can be separately compiled giving Ada 95 the ability to offer
classes much like Java, C++, and C#

Ada offers both static and dynamic binding of objects to
procedure calls

Dynamic binding is available through the tagged type’s classwide type
denoted as Name’class or by using a polymorphic variable

Ada objects:

No implicit calling of constructors and destructors

if desired, they must be invoked explicitly, but they are not needed

Single inheritance

although multiple inheritance can be simulated to some extent using generic

Subclasses inherit all items from a parent class and to restrict this, you
would have to use child library packages (nested directly inside of the
parent’s package)

Ada Example

Package PERSON_PKG is

type PERSON is tagged private;

procedure DISPLAY(P : in out PERSON);


type PERSON is tagged


NAME : STRING(1..30);



end record;



Package STUDENT_PKG is

type STUDENT is new PERSON with




end record;

procedure DISPLAY (ST: in STUDENT);



DISPLAY is being overridden from




Pcw : PERSON’class; // classwide

// version of Person

DISPLAY(P); // call Person’s display

DISPLAY(S); // call Student’s display

Pcw := P;

DISPLAY(Pcw); // Person’s display

Pcw := S;

DISPLAY(Pcw); // Student’s display

Ada’s mechanisms for objects is

built on top of previous mechanisms

and so is both awkward and less

flexible than C++, and inconsistent

as compared to Java/C#


Like Smalltalk, everything in Ruby is an object and all
computation is done via message passing

class definitions are executable, meaning that a class’
definition (structure or available methods) can change at run

for instance, you could have code that modifies a class at run
time so
that the class gains a new method

at run
time, a class is the union of all definitions that have been

all variables are reference variables to objects and all are

instance variable names are denoted by starting with @

instance variables are always private (accessor methods must be
written if you want to provide external access to an instance variable)

methods default to public, but can be private or protected

accessor/mutator methods can be easily generated by using
the shortcut functions attr_reader and attr_writer respectively

for instance: attr_reader :member1, :member2 will automatically
generate a getter method to return the value of member1

More on Ruby

Deriving a subclass is done through < as in

class subclass < parentclass

access control to methods can be changed at the subclass level (for
instance, if subclass above inherits method foo, subclass can alter the
access control from public to private or protected)

The Ruby module is used to control encapsulation and

All variables are polymorphic (they are typeless and so only
bound to a given object when assigned to point at it) and are
therefore dynamically bound to methods

While Ruby is a pure OOPL (and therefore will satisfy some OO
programmers), it is generally a weaker language than C++, Java
or C# in that it lacks the ability to more tightly control

what is inherited and how (no multiple inheritance)

access control

other OOPL features like abstract classes



primarily use is for dynamic html pages

JavaScript is similar to Java in syntax and

JavaScript, like Java, uses two types of data

objects and primitive data types

but from there, the treatment of objects differs:

Java: statically typed language

JavaScript: dynamically typed language with all variables being
reference variables (implicit pointers) much like in Lisp

JavaScript: does not have a class, objects are created dynamically
without a formal definition

so JavaScript does not support inheritance or polymorphism

JavaScript does not require that variables be declared, but even if they
are, they do not have to be typed

types are determined when the variable is assigned a value, and the type
changes as the value assigned changes (much like Lisp)

any variable can reference any primitive type or any object

JavaScript Objects

Objects have a collection of properties

These properties are their data members and methods

each data member is a pair

the name and its current value

functions and methods are objects themselves and referenced by
variables which point to them

to create an any object,
is used, creating a blank object

example: var my_object = new Object( );

to add to an object, assignment statements are used

example: = “Frank Zappa”; and my_object.occupation =

objects can be nested by now doing = new Object( );
and assigning = “none”;

if access is made to a property that does not exist, the value

to remove from an object, use delete as in delete my_object.occupation;

More on JavaScript

Functions/methods are defined
similar to properties:

define the function

function f( ) {…}

assign a variable to point at the

var x = f

constructors are defined as ordinary
functions and called (if defined)
whenever new is used


function musician(style, instrument,
age) { = style;
this.instrument = instrument;
this.age = age);}

my_object = new musician(“rock”,
“guitar”, 37);

JavaScript is like Java in that
it contains

most of the same control
structures as Java

the same arithmetic operators
as Java and the same style of
assignment statement

many of the same String
operations as Java

JavaScript is not intended for
scale applications

so this primitive and flexible
treatment of objects is
satisfactory if you need objects
in your script

but if you want to do OOP,
you would

Implementing Objects

To implement an object, there needs to be at least two mechanisms
available for easy construction and use:

a description of the data storage needed for the object

pointers to the object’s methods so that, if dynamically bound, the method
call can quickly be made

Both of these can be captured by having the compiler generate a
class instance record (CIR) at compile

any newly instantiated object uses the CIR as a template to generate the
storage space needed for the object

the CIR could contain a pointer to all methods, but either the CIR would
have to modified at run
time whenever the variable is altered to point at a
subclass (if the variable is polymorphic), or we would have to disallow
polymorphic variables

so we will use a different approach

instead, we might use a virtual method table for each class

this will differ for a

the CIR then points at the VMT for the class it is currently assigned to, and this
pointer changes whenever the variable is assigned to a different class

Example of CIRs

public class A {

public int a, b;

public void draw( ) {…}

public int area( ) {…}


public class B extends A {

public int c, d;

public void draw( ) {…}

public void sift() {…}


This becomes more complicated if multiple

inheritance is allowed, see figure 12.3 on page

563 to illustrate this in C++