Data Abstraction and Encapsulation

advertisement
Data Abstraction and Encapsulation
• Key research:
– Dennis & Van Horn
CACM, March '66
• first notion of abstract types and capabilities
– Parnas: "On the Criteria to be Used in Decomposing
Systems into Modules." CACM, Dec '72
– Liskov:
CLU
– Wulf/Shaw:
Alphard
– Lampson:
Euclid
– Good:
GYPSY
– Xerox:
Mesa
– Hoare/Brinch Hansen: monitors
– Wirth:
Modula & Modula-2
– Honeywell-Bull:
Ada
Parnas's Principles
• One must provide the intended user with all the
information needed to use the module and nothing
more.
• One must provide the implementer with all the
information needed to complete the module and
nothing more.
Data Abstraction
• Emphasis on behavior (operations capture behavior)
• Implementation is not important to user of abstraction
• In order to support data abstraction, language must
provide:
– linguistic construct
• permits abstraction to be implemented as a unit
• supports representation specification
– ways to limit access to object
• access should only be to defined operations
• no access to representation
--> clusters, modules, forms, packages, classes...
Simple - Data Only
package earth is
type continent is
(Africa, Antarctica, Asia, Australia, Europe, NorthAmerica,
SouthAmerica);
radius: constant float:= 6.4e6;
area: constant array (continent) of float:=
(30.3e9, 13.0e9, 43.3e9, 7.7e9, 10.4e9, 24.9e9, 17.8e9);
population : array (continent) of integer;
end earth;
Logical clustering
Information Hiding
package trig is
function sin(x: float) return Float;
function cos(x: float) return Float;
end trig;
package body trig is
pi: constant Float:= 3.14159;
function norm(x: float) return float is
...; - return x modulo 2*pi
function sin(x: float) return float is
...; --return the sine of norm(x)
function cosine (x: float) return float is
...; --return the cosine of norm(x)
end trig
Exporting
functions only
Implementation
is hidden
Simple Objects
- Creates one directory
package directory_object is
- exports two procs that
procedure insert(newname : in Name;
newnumber : in Number);
can operate on directory
procedure lookup(oldname : in Name;
- directory itself hidden
oldnumber : out Number;
from access
found : out Boolean);
end directory_object;
package body directory_object is
type Dirnode;
type Dirptr is access Dirnode;
type Dirnode is record
entryname : Name;
entrynumber : Number;
left, right : Dirptr;
end record;
root: dirptr;
Implements a
directory
(cont) Simple Objects
procedure insert(newname : in Name; newnumber : in Number) is
... -- add new newname, newnumber to the directory
procedure lookup(oldname : in Name;
oldnumber : out Number;
found : out Boolean);
... -- find oldname entry in directory
begin
...; -- initialize the directory
end directory_object;
-----------------directory-object.insert (me, 41039);
...
directory_object.lookup (me, mynumber, ok);
Operations user can
perform on directory
Object Classes
generic package directory_class is
procedure insert(newname: in Name; newnumber: in
Number);
procedure lookup(oldname: in Name; oldnumber: out
Number; found: out Boolean);
end directory_class;
package body directory_class is
type Dirnode;
type Dirptr is access Dirnode;
type Dirnode is record
entryname : Name;
entrynumber : Number;
left, right : Dirptr;
end record;
root: dirptr;
Describes an instance
of a directory
(cont) Object Classes
procedure insert(newname: in Name; newnumber: in Number) is
... -- add new newname, newnumber to the directory
procedure lookup(oldname: in Name; oldnumber: out Number;
found: out Boolean);
... -- find oldname entry in directory
begin
... -- initialize the directory
end directory_class;
-----------------package homedir is new directory_class
package workdir is new directory_class
workdir.insert (me, 41039);
homedir.insert (me, 30570);
workdir.lookup (me, mynumber, ok);
Derived
objects
No notion of
inheritance
Abstract Types - Motivation
datatype rational = rat of (int * int);
val zero = rat (0, 1);
and one = rat (1, 1);
fun op ++ (rat(m1, n1): rational,
rat(m2, n2): rational) =
rat (m1*n2 + m2*n1, n1*n2)
----------------------rat(3,2) --creates rational number 3/2
rat(6,4) --creates rational number 6/4
Abs Types - (cont) Motivation
if one ++ rat(1,2) = rat (6,4) then ... else ...
Won’t test =
although it should
rat(0,0) -- no corresponding
rat(1,0) -- rational numbers!
-----------------------Have: Rational = {rat(m,n) | m,n integer}
Desire: Rational = {rat(m,n) | m,n integer; n>0;
m,n have no common factor}
-- a type based on a (representation) type that does not exist
-- in common languages.
abstract type: based on a set of operations: constants, functions
and procedures -- values defined only indirectly.
Abstract Types - Example
abstype rational = rat of (int * int);
with
val zero = rat (0, 1);
and one = rat (1, 1);
fun op // (m: int, n: int) =
if n <> 0
then rat(m,n)
else ... -- invalid rational number
and op ++ (rat(m1, n1): rational, rat(m2, n2): rational) =
rat (m1*n2 + m2*n1, n1*n2)
Abs Types (cont) Example
and op == (rat(m1, n1): rational, rat(m2, n2): rational) =
(m1*n2 = m2*n1)
and float (rat(m,n): rational) =
m/n
end
----------------------val h = 1//2 --creates rational number 1/2
val i = 6//4 --creates rational number 6/4
if one ++ h = = i then ... else ...
-- now this works
Another Abstract Type
package directory_type is
type Directory is limited private;
procedure insert(dir: in out Directory; newname: in Name;
newnumber : in Number);
procedure lookup(dir: in Directory; oldname: in Name;
oldnumber: out Number; found: out Boolean);
private
type Dirnode;
type Directory is access Dirnode;
type Dirnode is record ... end record;
end directory_type;
Implementation
details in a
specification!
Another Abstract Type (cont)
package body directory_type is
procedure insert(dir: in out Directory; newname: in Name;
newnumber : in Number) is
... -- add new newname, newnumber to dir
procedure lookup(dir: in Directory; oldname: in Name;
oldnumber: out Number; found: out Boolean);
... -- find oldname entry in dir
end directory_type;
Using directory_type
use directory_type; -- allows dropping dot notation
homedir: Directory;
workdir: Directory;
...
insert (workdir, me, 41039);
insert (homedir, me, 97548);
...
lookup (workdir, me, mynumber, ok);
Objects and Abstract Types
• Abstract types are similar to built-in types and have firstclass status: values of the type are first-class. Objects, in
general, are not. In object example, homedir and workdir
couldn't be passed as arguments, for e.g.
• Abstract type notation is more natural: values and variables
of the type are arguments rather than dot-notated prefixes.
• Abstract types work in all programming paradigms.
Objects, being updatable entities, fit the imperative
programming style.
Generics
generic
capacity: in positive;
type Item is private;
package queue_class is
procedure append(newitem : in Item);
procedure remove(olditem : out Item);
end queue_class;
More Generics
package body queue_class is
items : array (1..capacity) of Item;
size, front, rear : Integer range 0..capacity;
procedure append(newitem : in Item) is
begin
... items(rear):= newitem; ...;
end;
procedure remove(olditem : out Item) is
begin
... olditem:= items(front); ...;
end
end;
begin
front:= 1; rear:= 0;
end queue_class;
Using queue_class
package line_buffer is new queue_class(120, Character);
type Transaction is record ... end record;
package audit_trail is new queue_class(100, Transaction);
T: Transaction;
...
line_buffer.append('*');
...
audit_trail.remove(T);
Generics with Dependent Types
generic
type Item is private;
type Sequence is array (Integer range <>) of Item;
with function precedes (x,y: Item) return Boolean;
package sorting is
procedure sort(seq : in out Sequence);
procedure merge(seq1, seq2 : in out Sequence;
seq : out Sequence);
end sorting;
Sorting (body)
package body sorting is
procedure sort(seq : in out Sequence) is
begin
...; if precedes(seq(i), seq(j)) then ...; ...;
end;
procedure merge(seq1, seq2 : in out Sequence;
seq : out Sequence) is
begin ...; end;
end sorting;
Using Generic
type Float_sequence is array(Integer range <>) of Float;
package ascending is new sorting(Float, Float_sequence, "<=");
package descending is new sorting(Float, Float_sequence, ">=");
...
type Trans_sequence is array(Integer range <>) of Transaction;
function earlier(t1, t2 : Transaction) return Boolean is
...; --return true if t1 precedes t2
end earlier;
package transaction_sorting is new sorting(Transaction,
Trans_sequence, earlier);
Arguments in Ada
Procedure/Function
abstraction
Generic
abstraction
argument type
First class value
yes
yes
Reference to a variable
yes
yes
Procedure/function abstraction
no
yes
type
no
yes
• Oddity that Ada does not allow procedure/function arguments to procedures
and functions.
• Not unusual to not allow type parameters to procedures/functions.
Related documents
Download