Introduction to Object Oriented Programming, 3rd Ed

Timothy A. Budd

Chapter 12

Implications of Substitution

Outline

  1. Roadmap
  2. Idealization of the is-a Relationship
  3. Memory Allocation - Stack and Heap Based
  4. The Problem with Substitution
  5. Memory Strategies
    1. Minimum Static Space Allocation
      1. Assigning a Larger Value to a Smaller Box
      2. The Slicing Problem
      3. Rules for Member Function Binding in C++
      4. Illustration
    2. Maximum Static Space Allocation
    3. Dynamic Memory Allocation
  6. Meaning of Assignment
    1. Copy Semantics versus Pointer Semantics
    2. Problems with Pointer Semantics
  7. An Old Joke Concerning Equality
    1. Equality and Identity
    2. Paradoxes of Equality, Part 1
    3. Paradoxes of Equality, Part 2
    4. Paradoxes of Equality, Part 3
  8. Chapter Summary

Other Material

Intro OOP, Chapter 12, Outline

Roadmap

In this chapter we will investigate some of the implications of the principle of substitution in statically typed object-oriented programming languages. In particular, we will consider:
Intro OOP, Chapter 12, Slide 01

Idealization of is-a Relationship

Unfortunately, practical programming language implementation issues complicate this idealized picture.

Intro OOP, Chapter 12, Slide 02

Memory Allocation - Stack and Heap Based

Generally, programming languages use two different techniques for allocation of memory.

Intro OOP, Chapter 12, Slide 03

The Problem with Substitution

class Window {
public:
	virtual void oops();
private:
	int height;
	int width;
};

class TextWindow : public Window {
public:
	virtual void oops();
private:
	char * contents;
	int cursorLocation;
};

	Window x; // how much space to set aside?
	TextWindow y;
	x = y; // what should happen here?










Intro OOP, Chapter 12, Slide 04

Memory Strategies

How much memory should be set aside for the variable x ?

1.
(Minimum Static Space Allocation) Allocate the amount of space necessary for the base class only. (C++)

2.
(Maximum Static Space Allocation) Allocate the amount of space for the largest subclass.

3.
(Dynamic Space Allocation) Allocate for x only the amount of space required to hold a pointer. (Smalltalk, Java)
Intro OOP, Chapter 12, Slide 05

Minimum Static Space Allocation

The language C++ uses the minimum static space allocation approach.

This is very efficient, but leads to some subtle difficulties.

What happens in the following assignment?

Window x;
TextWindow y;

x = y;
Intro OOP, Chapter 12, Slide 06

Assigning a Larger Value to a Smaller Box

Intro OOP, Chapter 12, Slide 07

The Slicing Problem

The problem is you are trying to take a large box and squeeze it into a small space. Clearly this won't work. Thus, the extra fields are simply sliced off.

Question - Does this matter?

Answer - Only if somebody notices.

Solution - Design the language to make it difficult to notice.

Intro OOP, Chapter 12, Slide 08

Rules for Member Function Binding in C++

The rules for deciding what member function to execute are complicated because of the slicing problem.

1.
With variables that are declared normally, the binding of member function name to function body is based on the static type of the argument (regardless whether the function is declared virtual or not).

2.
With variables that are declared as references or pointers, the binding of the member function name to function body is based on the dynamic type if the function is declared as virtual, and the static type if not.
Intro OOP, Chapter 12, Slide 09

Illustration

void Window::oops()
{	printf("Window oops\n"); }

void TextWindow::oops()
{	printf("TextWindow oops %d\n", cursorLocation);

TextWindow x;

Window a;
Window * b;
TextWindow * c;

a = x;	a.oops();	// executes Window version
b =  &x; b->oops();	// executes TextWindow or Window version;
c = &x; c->oops();	// executes TextWindow version
Intro OOP, Chapter 12, Slide 10

Maximum Static Space Allocation

A different approach would be to allocate the Maximum amount of space you would ever need.

Intro OOP, Chapter 12, Slide 11

Dynamic Memory Allocation

Intro OOP, Chapter 12, Slide 12

Meaning of Assignment?

What does it mean whan an instance of a class is assigned to another variable?
class Box {
	public int value;
}

Box x = new Box();
x.value = 7;
Box y = x;
y.value = 12;  // what is x.value?
Two possibilities:
Intro OOP, Chapter 12, Slide 13

Copy Semantics versus Pointer Semantics

If a value is indirectly accessed through a pointer, when an assignment is performed (or equality test is made) is the quantity assigned simply the pointer or is it the actual value?

Intro OOP, Chapter 12, Slide 14

Problems with Pointer Semantics

Intro OOP, Chapter 12, Slide 15

An Old Joke Concerning Equality

There is an old joke that goes something like this: A man walks into a pizza parlor and sits down. A waiter comes to the table and asks the man what he would like to order. The man looks around the room, then points to the woman sitting at the next table, and says ``I'll have what she is eating.'' The waiter thereupon walks to the womans table, picks up the half-eaten pizza from in front of her, and places it before the startled customer.

A classic confusion between equality and identity.

Intro OOP, Chapter 12, Slide 16

Equality and Identity

Of course, the meaning of equivalent is inheritently domain specific. Object-oriented languages allow the programmer to control the meaning of the equality test by allowing the redefinition of a standard method. (for example, equals in Java).
Intro OOP, Chapter 12, Slide 17

Paradoxes of Equality, Part 1

But child classes cannot change the type signature of overridden methods. This means the argument must often be more general than one would like:
class Object {
	public boolean equals (Object right) { 
		... 
	}
}

class PlayingCard extends Object {
	public boolean equals (Object right) {
		... // right must be object even if we are only
		... // interested in comparing cards to cards
	}
}
Intro OOP, Chapter 12, Slide 18

Paradoxes of Equality, Part 2

Because equality is a message sent to the left argument, there is no guarantee that properties such as symmetry or transitivity are preserved:

class Foo {
	boolean equals (Object right) { ... }
}

Foo a, b;

if (a.equals(b))  // even if this is true

if (b.equals(a))  // no guarantee that this is true

Intro OOP, Chapter 12, Slide 19

Paradoxes of Equality, Part 3

And if you add inheritance into the mix, the possibilities for paradoxical behavior increase even more.
class Parent {
	boolean equals (Object x) { ... }
}

class Child extends Parent {
	boolean equals (Object x) { ... }
}

Parent p;
Child c;

if (p.equals(c)) // will execute using the parent method

if (c.equals(p)) // will execute using the childs method
Intro OOP, Chapter 12, Slide 20

Chapter Summary

We have explored the implications that result from the inclusion of the principle of substitution in an object oriented programming language.
Intro OOP, Chapter 12, Slide 21