240 likes | 382 Views
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
E N D
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 istypecontinentis (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
Exporting functions only Implementation is hidden 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
Simple Objects - Creates one directory - exports two procs that can operate on directory - directory itself hidden from access package directory_object is procedure insert(newname : in Name; newnumber : in Number); procedure lookup(oldname : in Name; oldnumber : out Number; 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); funop ++ (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 Won’t test = although it should if one ++ rat(1,2) = rat (6,4) then ... else ... 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 first-class 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 isrecord ... 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 isarray(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 Generic abstraction 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.