2 0 0 5 -1 0 -0 7 Lennart Ed b lo m , Inst. f.
d atavetenskap
1
Lecture 12: Abstract data types
• Algebras
• Abstract data types
• Encapsulation and information hiding
• Parameterization
Algebras
Definition
An algebra A is a tuple
A = (D
1,…,D
m, f
1,…,f
n)
where every D
iis a set (called domain) and every f
jis a function f
jbetween domains (called operation), i.e
f
j:X
1×…×X
k→ Y where X
1,…,X
k,Y ∈ {D
1,…,D
m}.
Which kinds of data do we want to discuss?
… What can we do with it?
…
2 0 0 5 -1 0 -0 7 Lennart Ed b lo m , Inst. f.
d atavetenskap
3
Algebras vs programs
Unfortunately programs have much higher complexity. Why?
One problem: Other parts of the program may exploit implementation details that are not part of the functionality.
A program does not only describe the abstract functionality but first of all how it is realized
(= implemented), often in detail.
⇒ Correctness depends on arbitrary ”random”
assumptions
Every little detail may influence other parts of the program
Abstract data types
Abstract data types (ADT:s) is an attempt to apply algebraic concepts to programming languages:
• Characteristics of data and operations are described on an abstract level; nothing about implementation
• Other parts of the program cannot use implementation details
• Other units can only use the specified abstract
(invariable) properties; not implementation-related details (which may change)
• This is an example of data abstraction
2 0 0 5 -1 0 -0 7 Lennart Ed b lo m , Inst. f.
d atavetenskap
5
Encapsulation and information hiding
To reach these goals an ADT must fulfil two conditions:
• Encapsulation
The definition of an ADT specifies its name and its operations in one single syntactic unit (not scattered in several units). Other program units may refer to this definition (only) to use the ADT.
• Information hiding
The internal representation of data is not accessible for other program units.
equations:
isEmpty(empty) = true, isEmpty(push(s, e)) = false,
pop(push(s, e)) = s, pop(empty) = 〈error〉, top(push(s, e)) = e, top(empty) = 〈error〉
ADT stack is elem + boolean +
operations:empty: → stack
push: stack
xelem → stack, pop: stack → stack,
top: stack → elem, isEmpty: stack → boolean
Example of a formal specification
Algebraic specifikation of ADT stack
2 0 0 5 -1 0 -0 7 Lennart Ed b lo m , Inst. f.
d atavetenskap
7
Formal specification (2)
• What operations?
Constructors ( returns an object of the actual type) (”true” constructors, modifiers, destructors)
Inspectors (examines the inner structure) (selectors, predicates)
Comparators (compares equality, if not in the language)
• What equations? Rule of thumb:
One for each combination constructor - inspector
One for each combination constructor - destructor
Implementation
• Implementation of an ADT:
Interface - definition of types and operations on types, available for the ”clients”
Internal representation of the objects, implementation of operations. Invisible for the clients
For maximal flexibility: Need to be able to separate definition (interface) and implementation
• ”Rich” & ”restrictive” interface, completeness (cf DoA)
• Different languages give more or less support
Only ADT:s, or general modules?
Information hiding?
Separation of definition & specification?
How can we ”connect” modules? Freedom fr block struct.?
2 0 0 5 -1 0 -0 7 Lennart Ed b lo m , Inst. f.
d atavetenskap
9
Example: stack in Java
import java.io.*;
class stack {
private Vector s = new Vector();
public void push(elem e) { s.addElement(e);
}
public void pop() {
s.removeElementAt(s.size() - 1);
}
public elem top() { return s.lastElement();
}
public boolean isEmpty() { return s.size() = 0;
} }
Parameterized ADT:s
• If an ADT builds upon other, simpler ADT:s we often wish to be able to create different instances using parameters
stack(integer), stack(tree), stack(stack(tree)), …
sortedList(integer), sortedList(string), …
…
• N.B: These parameters are data types!
• Problem: In some languages (e.g old versions of Java) it is not possible to explicitly create different instances
⇒ We cannot distinguish between sortedList(integer)
and sortedList(string)
2 0 0 5 -1 0 -0 7 Lennart Ed b lo m , Inst. f.
d atavetenskap
11
Example: stack in ML
exception EmptyStack
abstype ‘a stack = Stack of ‘a list with
val empty = Stack []
fun push (Stack s, e) = Stack (e::s) fun pop (Stack []) = raise EmptyStack | pop (Stack (_::xs)) = Stack xs fun top (Stack []) = raise EmptyStack | top (Stack (x::_)) = x
fun isEmpty (Stack s) = s=[]
end;
val stack1 = push (empty, 1);
> val stack1 = -:int stack
val stack2 = push(push(empty,(1,”Otto”)),(2,”Olga”));
> val stack2 = -:(int*string)stack
Example: MyStack in HASKELL
module MyStack ( MyStack, empty, push, pop, top, isEmpty, smallest ) where
newtype (Ord a) => MyStack a = StackOf [a]
empty :: (Ord a) => MyStack a empty = StackOf []
push (StackOf xs) x = StackOf (x : xs) pop (StackOf (x:xs)) = StackOf xs top (StackOf (x:xs)) = x
isEmpty (StackOf xs) = xs == []
smallest (StackOf (x:xs)) = getSmallest x xs getSmallest x [] = x
getSmallest x (y:ys) | x < y = getSmallest x ys | otherwise = getSmallest y ys
visible
The parameter must have an order relation `<`
Not visible!
2 0 0 5 -1 0 -0 7 Lennart Ed b lo m , Inst. f.
d atavetenskap
13
Modules in ML-
an example of encapsulation
• ML has very powerful, general (and therefore difficult to understand?) modules:
> Structures: package with concrete definitions / implementations
> Signatures: types of a structure
> Functors: parameterized structures
Example: stack in ML again
signature StackItem = sig type item
val isequal: item -> item -> bool end;
signature Stack = sig type item type stack
exception EmptyStack val empty: stack
val push: (stack * item) -> stack .. ..and so on
end;
functor MkStack(Item:StackItem):> Stack = struct
type myitem = Item.item type stack = myitem list exception EmptyStack val empty = []
2 0 0 5 -1 0 -0 7 Lennart Ed b lo m , Inst. f.
d atavetenskap
15
Example: stack in ML again (2)
structure Pair:StackItem = struct
type item = int * string
fun isequal (i1,s1) (i1,s2) = i1=i2 andalso s1=s2 end;
structure PairStack = MkStack(Pair);
val mystack = PairStack.push (PairStack.empty, (3,”Haskell”));