here

advertisement
Genericity
Parameterizing by Type
1
Generic Class
• One that is parameterized by type
» Works when feature semantics is common to a set
of types
• On object declaration the parameter is assigned a
type
» For example
catalogue : ARRAY [ PERSON ]
» We want an array of references to persons
» All the array operations for catalogue are
customized to use persons
2
Common Generic Classes
• Collection classes – classes that are collections of
objects
» Strong typing requires specifying a type
» But feature semantics is independent of type
• Examples
» Sets, Stacks, Arrays, Queues, Sequences
a : ARRAY [ MATRIX_ELEMENT ]
a : ARRAY [ INTEGER ]
a : ARRAY [ STACK [ ELEPHANTS ] ]
3
Your Generic Classes
• You can write generic classes
• Why is this useful?
» reuse
» reliability
4
Understanding Genericity
• We need
» lists of INTEGER, lists of BOOK, lists of STRING etc.
• Without genericity we have
» INTEGER_LIST, BOOK_LIST, STRING_LIST
• Problem — Reusability.
» The basic operations (e.g. extend)are essentially the
same.
» Have to re-write essentially the same code over and over
again.
» Violation of the Single Choice Principle — changing
STACK requires multiple changes, instead of a change
at a single point.
5
Generic Stack
class STACK [ G ] feature
count : INTEGER -- number of elements
empty : BOOLEAN is do ... end
full : BOOLEAN is do ... end
item : G is do ... end
put ( x : G ) is do ... end
remove is do ... end
end -- STACK
• Can use parameter G wherever a type is expected
6
Generic Array
class ARRAY [ P ] creation make
feature
make ( minIndex , maxIndex : INTEGER ) is do ... end
lower, upper, count : INTEGER
put ( value : P ; index : INTEGER ) is do ... end
infix "@" , item ( index : INTEGER ) : P is do ... end
end -- ARRAY
7
Using the Generic Array
circus : ARRAY [ STACK [ ELEPHANTS ] ]
create circus.make ( 1 , 200 )
st_el : STACK [ ELEPHANTS ] -- element to put in the array
create st_el
circus.put ( st_el , 30 ) -- put an element into the array
st_el2 : STACK [ ELEPHANTS ]
st_el2 := circus @ 101
-- get an element from the array
8
Types of Genericity
• Types
» Unconstrained
» Constrained
• The previous examples showed unconstrained
genericity
» Any type could be passed as a parameter
9
Constrained Genericity
• Used when the generic type parameters must satisfy
some conditions
• The following makes sense only if P has the
feature ≥
class VECTOR [ P ] feature
...
minimum ( x , y : P ) : P is do
if x ≥ y then
Result := y
How we enforce
else
constraints is
Result := x
discussed in
end
Inheritance Techniques
...
end
10
Discussion on Genericity
• What programming languages offer genericity that
you know of? Java? C++? Other?
• C++ has the template: Set < int > s ;
• Java has no genericity – can it be faked?
• What is the effect of genericity on
» compile time
» size of the generated code
» execution time
» execution space
• Warning: generics cheap in Eiffel – expensive in C++
11
Java Stack
public class Stack {
private int count;
private int capacity;
private int capacityIncrement;
private Object[] itemArray; // instead of ARRAY[G]
Stack() {
//constructor limited to class name
count= 0;
capacity= 10;
capacityIncrement= 5;
itemArray= new Object[capacity];
// no pre/postconditions/invariants
}
public boolean empty() {
return (count == 0);
}
12
Java Stack (cont.)
public void push(Object x) {
if(count == capacity) {
capacity += capacityIncrement;
Object[] tempArray= new Object[capacity];
for(int i=0; i < count; i++)
tempArray[i]= itemArray[i];
itemArray= tempArray;
}
itemArray[count++]= x;
}
public Object pop() {
if(count == 0) // no preconditions;
// hence defensive programming
return null;
else return itemArray[--count];
}
13
Java Stack (cont.)
public Object peek() {
if(count == 0)
return null;
else return itemArray[count-1];
}
}
// end Stack; no class invariant
public class Point {
public int x;
public int y;
}
14
Java Stack runtime error
class testStack {
public static void main(String[] args) {
Stack s = new Stack();
Point upperRight = new Point();
upperRight.x= 1280;
// breaks information hiding
upperRight.y= 1024;
// cannot guarantee any contract
s.push("red");
s.push("green");
// push some String
s.push("blue");
// objects on the stack
s.push(upperRight);
// push a POINT object on the stack
while(!s.empty()) {
// cast all items from OBJECT
String color = (String) s.pop();
// to STRING in order to print
System.out.println(color);
}}}
// causes a run-time error in Java
// ClassCastException: Point at testStack.main(testStack.java:18)
// In Eiffel it is a compile time error
15
Does run-time vs. compile time matter?
• Principle: When flying a plane, run-time is too late to
find out that you don’t have landing gear!
• Always better to catch errors at compile time!
• This is the main purpose of Strong Typing [OOSC2,
Chapter 17].
• Genericity helps to enforce Strong Typing, i.e. no runtime typing errors
» LIST[INTEGER]
» LIST[BOOK]
» LIST[STRING]
16
Download