Chapter 11 Abstract Data Types and Encapsulation Concepts
Chapter 11 Abstract Data Types and Encapsulation Concepts ISBN 0 -321 -33025 -0
Chapter 11 Topics • • The Concept of Abstraction Introduction to Data Abstraction Design Issues for Abstract Data Types Language Examples Parameterized Abstract Data Types Encapsulation Constructs Naming Encapsulations 2
The Concept of Abstraction • An abstraction is a view or representation of an entity that includes only the most significant attributes • The concept of abstraction is fundamental in programming (and computer science) • Nearly all programming languages support process abstraction with subprograms, e. g. , sort(list, length); • Nearly all programming languages designed since 1980 support data abstraction 3
Introduction to Data Abstraction • An abstract data type is a user-defined data type that satisfies the following two conditions: – The representation of, and operations on, objects of the type are defined in a single syntactic unit – The representation of objects of the type is hidden from the program units that use these objects, so the only operations possible are those provided in the type's definition 4
Advantages of Data Abstraction • Advantage of the first condition – Program organization, modifiability (everything associated with a data structure is together), and separate compilation • Advantage the secondition – Reliability--by hiding the data representations, user code cannot directly access objects of the type or depend on the representation, allowing the representation to be changed without affecting user code – e. g. , stack implementation may be array or linked list, etc. 5
Design Issues • A syntactic unit to define an ADT • Built-in operations – Only a few are broad enough to apply – Assignment – Comparison • Common operations, designer provides – – Iterators Accessors Constructors Destructors • Parameterized ADTs 6
Language Examples: Ada • The encapsulation construct is called packages – Specification package (the interface) – Body package (implementation of the entities named in the specification) • Information Hiding – The representation of type appears in a part of the specification called the private part • More restricted form with limited private types – Define the ADT as a pointer and provide the pointed-to structure’s definition in the body package 7
An Example in Ada package Stack_Pack is type stack_type is limited private; max_size: constant : = 100; function empty(stk: in stack_type) return Boolean; procedure push(stk: in out stack_type; elem: in Integer); procedure pop(stk: in out stack_type); function top(stk: in stack_type) return Integer; private -- hidden from clients type list_type is array (1. . max_size) of Integer; type stack_type is record list: list_type; topsub: Integer range 0. . max_size) : = 0; end record; end Stack_Pack 8
Language Examples: C++ • Based on C struct type and Simula 67 classes • The class is the encapsulation device • All of the class instances of a class share a single copy of the member functions • Each instance of a class has its own copy of the class data members • Instances can be stack dynamic (access via variable), or heap dynamic (access via pointer) 9
Language Examples: C++ (continued) • Information Hiding – Private clause for hidden entities – Public clause for interface entities – Protected clause for inheritance 10
Language Examples: C++ (continued) • Constructors: – Functions to initialize the data members of instances (they do not create the objects) – May also allocate storage if part of the object is heap-dynamic – Can include parameters to provide parameterization of the objects – Implicitly called when an instance is created – Can be explicitly called – Name is the same as the class name 11
Language Examples: C++ (continued) • Destructors – Functions to cleanup after an instance is destroyed; usually just to reclaim heap storage – Implicitly called when the object’s lifetime ends – Should not be explicitly called – Name is the class name, preceded by a tilde (~) 12
An Example in C++ class stack { private: int *stack. Ptr, max. Len, top. Ptr; public: stack() { // a constructor stack. Ptr = new int [100]; max. Len = 99; top. Ptr = -1; }; ~stack () {delete [] stack. Ptr; }; void push (int num) {…}; void pop () {…}; int top () {…}; int empty () {…}; } 13
Evaluation of ADTs in C++ and Ada • C++ support for ADTs is similar to expressive power of Ada • Both provide effective mechanisms for encapsulation and information hiding • Ada packages are more general encapsulations – program unit that gains visibility to Ada package can access public entities by name – in C++, must be accessed through a class instance - cleaner 14
Language Examples: Java • Similar to C++, except: – All user-defined types are classes (no struct) – All objects are allocated from the heap and accessed through reference variables – Individual entities in classes have access control modifiers (private or public), rather than clauses – Java has a second scoping mechanism, package scope, which can be used in place of friends • All entities in all classes in a package that do not have access control modifiers are visible throughout the package 15
An Example in Java class Stack. Class { private: private int [] *stack. Ref; private int max. Len, top. Index; public Stack. Class() { // a constructor stack. Ref = new int [100]; max. Len = 99; top. Ptr = -1; }; public void push (int num) {…}; public void pop () {…}; public int top () {…}; public boolean empty () {…}; } 16
Language Examples: C# • Based on C++ and Java • Adds two access modifiers, internal and protected internal • All class instances are heap dynamic • Default constructors are available for all classes • Garbage collection is used for most heap objects, so destructors are rarely used • structs are lightweight classes that do not support inheritance 17
Language Examples: C# (continued) • Common solution to need for access to data members: accessor methods (getter and setter) • Using accessors better than making data public because: – read-only access is possible (getter, no setter) – setters can include constraints (e. g. , date) – implementation of data member can change • C# provides properties as a way of implementing getters and setters without requiring explicit method calls 18
C# Property Example public class Weather { public int Degree. Days {//** Degree. Days is property get {return degree. Days; } set {if (value < 0 || value > 30) //implicit value Console. Write. Line(“Out of range); else degree. Days = value; } } private int degree. Days; . . . }. . . Weather w = new Weather(); int degree. Days. Today, old. Degree. Days; . . . w. Degree. Days = degree. Days. Today; // treat as public, call set old. Degree. Days = w. Degree. Days; // call get 19
C# Struct • Lightweight class • Can have constructors, properties, methods, data fields, can implement interfaces • No inheritance • Value types rather than reference types • Still created with new 20
ADTs in Ruby • • Support for ADTs via classes Instance variable names begin with @ Class variables names begin with @@ Instance methods begin with def close with end • Class methods distinguished by having the class name appended to the beginning of their names with a period separator • Constructors are named initialize 21
ADTs in Ruby (continued) • Members can be public (default) or private • Data members must be private • Classes are dynamic – members can be added at any time • Methods can be removed • Trades readability and reliability for flexibility – must find all definitions in program to know current definition of class 22
Ruby Example class Stack. Class def initialize @stack. Ref = Array. new @max. Len = 100 @top. Index = -1 end def push(number) if @top. Index == @max. Len puts “Error in push – stack is full” else @top. Index = @top. Index + 1 @stack. Ref[@top. Index] = number end 23
Ruby Example (continued) def pop if @top. Index == -1 puts “Error in pop – stack is empty” else @top. Index = @top. Index – 1; end def top @stack. Ref[@top. Index] end def emtpy @top. Index == -1 end # of Stack class 24
Ruby Example (continued) #Test code for Stack. Class my. Stack = Stack. Class. new my. Stack. push(42) my. Stack. push(29) puts “Top element is: #{my. Stack. top}” my. Stack. pop # The following produces an error my. Stack. pop 25
Parameterized Abstract Data Types • Parameterized ADTs allow designing an ADT that can store any type elements • Also known as generic classes • C++ and Ada provide support for parameterized ADTs • Java 5. 0 provides a restricted form of parameterized ADTs • C# 2005 includes generic classes 26
Parameterized ADTs in Ada • Ada Generic Packages – Make the stack type more flexible by making the element type and the size of the stack generic Max_size: Positive; type Elem_Type is Private; package Generic_Stack is type Stack_Type is limited private; function Top(Stk: in Stack_Type) return Elem_type; private type List_Type is array(1. . Max_Size) of Element_Type; type Stack_Type is record List : List_Type; Topsub : Integer range 0. . Max_size : = 0; end record; end Generic_Stack; Package Integer_Stack is new Generics_Stack(100, Integer); Package Float_Stack is new Generics_Stack(100, Float); 27
Parameterized ADTs in C++ • Templates create generic classes template <typename Type> class stack { … stack (int size) { stk_ptr = new Type[size]; max_len = size - 1; top = -1; }; … } stack<int> stk(100); 28
Parameterized ADTs in Java • Added in Java 5. 0 • Most collection classes are parameterized Collection<? > c = new Array. List<String>(); • Users can define generic classes 29
Parameterized ADTs in C# • • Added in 2005 Similar to Java No wildcard classes Can have indexed elements, can use strings as indexes 30
Encapsulation Constructs • Large programs have two special needs: – Some means of organization, other than simply division into subprograms – Some means of partial compilation (compilation units that are smaller than the whole program) • Obvious solution: a grouping of subprograms that are logically related into a unit that can be separately compiled (compilation units) • Such collections are called encapsulation 31
Nested Subprograms • Organizing programs by nesting subprogram definitions inside the logically larger subprograms that use them • Nested subprograms are supported in Ada , Fortran 95, Ruby and Python • Not used as a primary organizing construct 32
Encapsulation in C • Files containing one or more subprograms can be independently compiled • The interface is placed in a header file • Problem: the linker does not check types between a header and associated implementation • #include preprocessor specification 33
Encapsulation in C++ • Similar to C • With templates, function definitions (not just interface) must be accessible • Addition of friend functions that have access to private members of the friend class (e. g. , facilitates matrix-vector multiplication, where function must reside in one class such as matrix but must have access to other class) 34
Ada Packages • Ada specification packages can include any number of data and subprogram declarations • Ada packages can be compiled separately • A package’s specification and body parts can be compiled separately • With package, no need for friends (e. g. , put matrix and vector in same package) 35
C# Assemblies • A collection of files that appear to be a single dynamic link library or executable • Each file contains a module that can be separately compiled • A DLL is a collection of classes and methods that are individually linked to an executing program • C# has an access modifier called internal; an internal member of a class is visible to all classes in the assembly in which it appears 36
Naming Encapsulations • Large programs may be written by many developers working independently, Need a way for them to name variables without worrying about overlaps • A naming encapsulation is used to create a new scope for names • Naming encapsulations are logical encapsulations; need not be contiguous 37
Naming Encapsulations (cont) • C++ Namespaces – Can place each library in its own namespace and qualify names when used outside with the namespace – C# also includes namespace My. Stack { // Stack declarations } My. Stack: : top. Ptr; // use namespace to qualify using My. Stack: : top. Ptr; // using directive using namespace My. Stack; // global directive 38
Naming Encapsulations (cont) • Java Packages – Packages can contain more than one class definition; classes in a package are partial friends (access to public, protected, no access specifier) – Clients of a package can use fully qualified name or use the import declaration • Ada Packages – Packages are defined in hierarchies which correspond to file hierarchies – Visibility from a program unit is gained with the with clause 39
Naming Encapsulations (cont) • Ruby Modules – Modules are collections of methods and constants – Cannot be instantiated, do not define variables – To gain access, use require filename module My. Stuff PI = 3. 14159265 def My. Stuff. mymeth 1(p 1). . . end require My. Stuff. File // stored in My. Stuff. File. . . My. Stuff. mymeth 1(x). . . 40
Summary • The concept of ADTs and their use in program design was a milestone in the development of languages • Two primary features of ADTs are the packaging of data with their associated operations and information hiding • Ada provides packages that simulate ADTs • C++ data abstraction is provided by classes • Java’s data abstraction is similar to C++ • Ada and C++ allow parameterized ADTs • C++, C#, Java, and Ada provide naming encapsulation 41
- Slides: 41