Title: Chapter 3: Data Abstraction: The Walls
1Chapter 3 Data Abstraction The Walls
- Chien Chin Chen
- Department of Information Management
- National Taiwan University
2Abstract Data Types (1/10)
- Modularity
- Keeps the complexity of a large program
manageable by systematically controlling the
interaction of its components. - A modular program is
- Easier to write.
- Easier to read.
- Easier to modify.
- Eliminates redundancies.
- Isolates errors.
3Abstract Data Types (2/10)
- Modular programs usually consist of
- Existing modules.
- Modules you have to write.
- Modules communicate with each other through a
clear set of specifications. - A modules specifications should
- Detail how the module behaves.
- Be independent of the modules implementation.
4Abstract Data Types (3/10)
- Functional abstraction
- Separates the purpose and use of a module from
its implementation. - Hides the implementation details within a module.
- Makes these details inaccessible from outside the
module. - Knowing what each module will do but not how each
will eventually do it.
5Abstract Data Types (4/10)
Abstraction information hiding are like walls
around the modules!!
Figure 3-1 Isolated tasks the implementation of
task T does not affect task Q
6Abstract Data Types (5/10)
- The isolation of modules cannot be not total!!
- A functions specification, or contract,
describes how it interacts with other modules.
Contract If you use the function in this
way, this is exactly what it will do for you!!
7Abstract Data Types (6/10)
- Data abstraction
- Usually, the solution to a problem requires
operations on data. - Typical operations on data
- Add data to a data collection.
- Remove data from a data collection.
- Ask questions about the data in a data
collection. - Not all problems use or require these operations.
- Data abstraction asks you to think what you can
do to a collection of data independently of how
you do it.
8Abstract Data Types (7/10)
- With data abstraction
- Other modules of the solution will know what
operations they can perform on the data, but they
should not depend on how the data is stored or
how the operations are performed. - Data abstraction is a natural extension of
functional abstraction.
9Abstract Data Types (8/10)
- Abstract data type (ADT)
- An ADT is composed of
- A collection of data.
- A set of operations on that data.
- E.g., a list of addresses with insert, remove,
and retrieve operations. - Specifications of an ADT indicate what the ADT
operations do, - Should not specify how to store the data nor how
to carry out the operations. - For example, for the above ADT should not specify
whether to store the data in consecutive memory
locations or in disjoin memory locations.
10Abstract Data Types (9/10)
- When a program must perform operations on data.
- You should first design an abstract data type and
carefully specify what the ADT operations are to
do. - Then, you implement the operations with a data
structure. - A data structure is a construct that you can
define within a programming language to store a
collection of data. - E.g., array or linked-list for storing a list of
addresses.
11Abstract Data Types (10/10)
Figure 3-4 A wall of ADT operations isolates a
data structure from the program that uses it
ADT realizes data abstractions goal of
separating the operations on data from the
implementation of these operations.
12The ADT List (1/12)
- LIST
- Lists contain items of the same type.
- Except for the first and last items in a list,
each item has a unique predecessor and a unique
successor. - Head (or front) does not have a predecessor.
- Tail (or end) does not have a successor.
milk eggs butter apples bread chicken
1 2 3 4 5 6
- Items are referenced by their position within the
list. - E.g., position 1, 2.
13The ADT List (2/12)
- Specifications of the ADT List operations.
- Add an item to the list, remove, retrieve
- Do not specify how to perform the operations or
how to store the list. - ADT operations can be used in an application
without the knowledge of how the operations will
be implemented.
14The ADT List (3/12)
- ADT List Operations
- Create an empty list.
- Destroy a list.
- Determine whether a list is empty.
- Determine the number of items in a list.
- Insert an item at a given position in the list.
- Delete the item at a given position in the list.
- Look at (retrieve) the item at a given position
in the list.
15The ADT List (4/12)
- Operation Contract (specification) for the ADT
List - ListItemType
- The type of the items stored in the list.
-
- createList()
- Creates an empty list.
- destroyList()
- Destroys a list.
- isEmpty()boolean query
- Determines whether this list is empty.
- getLength()integer query
- Returns the number of items that are in this
list.
16The ADT List (5/12)
- insert(in indexinteger, in newItemListItemType,
out successboolean) -
- Inserts newItem at position index of this list,
if 1 lt index lt getLenth()1. - If index lt getLength(), items are renumbered as
follows the item at index becomes the item at
index 1, them item at index 1 becomes the item
at index 2, and so on. - The success flag indicates whether the insertion
was successful.
17The ADT List (6/12)
- remove(in indexinteger, out successboolean)
-
- Remove the item at position index of this list,
if 1 lt index lt getLength(). - If index lt getLength(), items are renumbered as
follows the item at index 1 becomes the index
at index, the item at index 2 become the item
at index 1, and so on. - The success flag indicates whether the deletion
was successful.
18The ADT List (7/12)
- retrieve(in indexinteger, out dataItemListItemTy
pe, out successboolean) query -
- Copies the item at position index of this list
into dataItem, if 1 lt index lt getLength(). - The list is left unchanged by this operation.
- The success flag indicates whether the retrieval
was successful.
19The ADT List (8/12)
- Pseudocode to create the list
- milk, eggs, butter
- aList.createList()
- aList.insert(1, milk, success)
- aList.insert(2, eggs, success)
- aList.insert(3, butter, success)
milk
eggs
butter
20The ADT List (9/12)
-
- Insert bread after milk
- aList.insert(2, bread, success)
- Insert juice at end of list
- aList.insert(5, juice, success)
milk eggs butter
milk bread eggs butter
milk bread eggs butter juice
21The ADT List (10/12)
- Remove eggs
- aList.remove(3, success)
milk bread eggs butter juice
milk bread butter juice
22The ADT List (11/12)
- Pseudocode function that displays a list
-
-
- Note that the function displayList does not
depend on how you implement the list. - The function will work regardless of whether you
use an array or other data structure to store the
lists data.
displayList(in aListList) for (position 1 to
aList.getLength()) aList.retrieve(position,
dataItem, success) Display dataItem //
end for
23The ADT List (12/12)
Figure 3-7 The wall between displayList and the
implementation of the ADT list
24The ADT Sorted List (1/3)
- The ADT sorted list
- Maintains items in sorted order.
- Inserts and deletes items by their values, not
their positions. - Operation Contract for the ADT Sorted List
- ListItemType
- The type of the items stored in the list.
-
- sortedIsEmpty()booleanquery
- Determines whether this sorted list is empty.
- sortedGetLength()integerquery
- Returns the number of items that are in this
sorted list.
25The ADT Sorted List (2/3)
- sortedInsert(in newItemListItemType, out
successboolean) - Insert newItem into its proper sorted position in
this sorted list. - The success flag indicates whether the insertion
was successful. - sortedRemove(in anItemListItemType, out
successboolean) - Delete anItem from this sorted list.
- The success flag indicates whether the deletion
was successful.
26The ADT Sorted List (3/3)
- sortedRetrieve(in indexinteger, out
dataItemListItemType,out success
boolean)query - Set dataItem to the item at position index of
this sorted list, if 1 lt index
ltsortedGetLength(). - The list is left unchanged by this operation.
- The success flag indicates whether the retrieval
was successful. - locatePosition(in anItemListItemType, out
isPresentboolean)integerquery - Returns the position where anItem belongs or
exists in this sorted list. - The isPresent flag indicates whether anItem is
currently in the list. - The item anItem and the list are unchanged.
27Designing an ADT
- Questions to ask when designing an ADT
- What data does a problem require?
- What operations does a problem require?
- The design of an ADT should evolve naturally
during the problem-solving process.
28Designing an ADT Example An Appointment Book
(1/6)
- Imagine that you want to create a appointment
book that spans a one-year period. - To define an ADT appointment book.
- Data appointments (date, time, purpose).
- Operation specification.
29Designing an ADT Example An Appointment Book
(2/6)
- createAppointmentBook()
- Creates an empty appointment book.
- destroyAppointmentBook()
- Destroys an appointment book.
- isAppointment(in apptDateDate, in
apptTimeTime)boolean query - Returns true if an appointment exists for the
date and time specified otherwise returns false.
30Designing an ADT Example An Appointment Book
(3/6)
- makeAppointment(in apptDateDate, in
apptTimeTime, in purposestring)boolean - Insert the appointment for the apptDate,
apptTime, and purpose specified as long as it
does not conflict with an existing appointment. - Returns true if successful, false otherwise.
- cancelAppointment(in apptDateDate, in
apptTimeTime)boolean - Deletes the appointment for the apptDate and
apptTime specified. - Returns true if successful, false otherwise.
31Designing an ADT Example An Appointment Book
(4/6)
-
- checkAppointment(in apptDateDate, in
apptTimeTime, out purposestring)query - Retrieves the purpose of the appointment at the
given appDate/appTime, if one exists. Otherwise,
purpose is set equal to a null string.
32Designing an ADT Example An Appointment Book
(5/6)
- Using ADT appointment book
- You can use the operations to design other
applications or modules.
// change the date or time of an
appointment read(oldDate, oldTime, newDate,
newTime) // get purpose of appointment apptBook.c
heckAppointment(oldDate, oldTime,
oldPurpose) if(oldPurpose not null) // a
scheduled appointment? // see if new date/time
is available if(apptBook.isAppointment(newDate,
newTime)) // new date/time is booked
write(You already have an appointment at ,
newTime, on , newDate)
33Designing an ADT Example An Appointment Book
(6/6)
else // new date/time is available
apptBook.cancleAppointment(oldDate, oldTime)
if(apptBook.makeAppointment(newDate, newTime,
oldPurpose)) write(Your appointment has
been rescheduled to , newTime, on ,
newDate) // end if else write(You do
not have an appointment at , oldTime, on ,
oldDate)
You can design applications of ADT operations
without knowing how the ADT is implemented.
34Designing an ADT Example ADTs That Suggest
Other ADTs (1/2)
- It is not unusual for the design of one ADT to
suggest other ADTs. - Suppose you want to design a database of recipes.
- This database is an ADT
- Data recipes.
- Operations
- insertRecipe
- deleteReciple
- retrieveRecipe.
35Designing an ADT Example ADTs That Suggest
Other ADTs (2/2)
- Suppose you want to design an operation that
scales a recipe retrieved from the database. - If the recipe is for n people, you want to revise
it so that it will serve m people. - Each recipe contains measurements such as 21/2
cups, 1 tablespon, and ¼ teaspon. - This problem suggests another ADT measurement
- Data measures (quantity, unit).
- Operations getMeasure, setMeasure, scaleMeasure,
convertMeasure. - When you finally implement the scale operation,
you can use the ADT measurement. - Help to represent data in a more object-oriented
way.
36Implementing ADTs (1/3)
- ADT Implementation
- Choose the data structure to represent the ADTs
data. - Write functions that access the data in
accordance with the ADT operation specifications. - Implementation details should be hidden behind a
wall of ADT operations. - A program (client) should only be able to access
the data structure by using the ADT operations.
37Implementing ADTs (2/3)
Walls specifications or operation contracts.
Hide the data structure (used to store data) and
the implementations of the ADT operations.
38Implementing ADTs (3/3)
- The disadvantage of violating the wall.
- In this chapter, we will use an array items to
store an ADT lists data.
firstItem items0 instead of using retrieve.
If you changed to another implementation (e.g.,
linked list) of the list, the program would be
incorrect.
39C Classes (1/3)
- C provides a way for us to enforce the wall of
an ADT. - Preventing access of the data structure other
than by using the ADT operations. - A C class defines a new data type.
- E.g., an ADT.
- A class contains data members and member
functions. - By default, all members in a class are private.
- But you can specify them as public.
- Encapsulation hides implementation details.
- An object is an instance of a class.
40C Classes (2/3)
Figure 3-10 An objects data and methods are
encapsulated
41C Classes (3/3)
- Each class definition is placed in a header file.
- Classname.h
- A programmer who uses your class (module) in a
program usually sees only header file. So, the
documentation of the class should be placed in
the header file. - The implementation of a classs methods are
placed in an implementation file. - Classname.cpp
42C Classes The header file
- / _at_file Sphere.h /
- const double PI 3.14159
- class Sphere
-
- public
- Sphere() // Default
constructor - Sphere(double initialRadius) // Constructor
- void setRadius(double newRadius)
- double getRadius() const // cant change data
members - double getDiameter() const
- double getCircumference() const
- double getArea() const
- double getVolume() const
- void displayStatistics() const
- private
- double theRadius // data members should
be private - // end Sphere
43C Classes Constructors (1/2)
- Constructors
- Create and initialize new instances of a class.
- Invoked when you declare an instance of the
class. - E.g., Sphere s
- Have the same name as the class.
- Have no return type, not even void.
- A class can have several constructors.
- E.g., Sphere() and Sphere(double newRadius)
- A default constructor has no arguments.
- The compiler will generate a default constructor
if you do not define any constructors. - If you define a constructor that has arguments,
but omit the default constructor, the compiler
will not generate one for you. - The compiler-generated default constructor might
not initialize data members to values that you
will find suitable.
44C Classes Constructors (2/2)
- The implementation of a method qualifies its name
with the scope resolution operator - The implementation of a constructor
- Sets data members to initial values
- Can use an initializer to initialize data
members. - Or simply use an assignment statement
- theRadius 1.0
- Cannot use return to return a value!!
SphereSphere() theRadius(1.0) // end
default constructor
SphereSphere() theRadius 1.0
or
45C Classes Destructors
- Destructor
- Destroys an instance of an object when the
objects lifetime ends. - Each class has only one destructor.
- For many classes, you can omit the destructor.
- The compiler will generate a destructor if you do
not define one. - For now, we will use the compilers destructor.
46C Classes The implementation file (1/2)
- / _at_file Sphere.cpp /
- include ltiostreamgt // for cout function
- using namespace std
- include "Sphere.h" // header file
- SphereSphere() theRadius(1.0)
-
- // end default constructor
- SphereSphere(double initialRadius)
-
- if (initialRadius gt 0)
- theRadius initialRadius
- else
- theRadius 1.0
- // end constructor
47C Classes The implementation file (2/2)
- void SpheresetRadius(double newRadius)
-
- if (newRadius gt 0)
- theRadius newRadius
- else
- theRadius 1.0
- // end setRadius
- double SpheregetRadius() const
-
- return theRadius
- // end getRadius
- double SpheregetArea() const
-
- return 4.0 PI theRadius theRadius
- // end getArea
- ...
To allow users to manipulate private data
48C Classes Using the class Sphere
- include ltiostreamgt
- using namespace std
- include "Sphere.h" // header file
- int main() // the client
-
- Sphere unitSphere
- Sphere mySphere(5.1)
- cout ltlt mySphere.getDiameter() ltlt endl
- . . .
- // end main
Include the header file
Invoke different constructors
The client invokes the classs public member
functions to access private data members.
49Inheritance in C (1/2)
- A common way to create new classes in C.
- A derived class (subclass) inherits any of the
publicly defined methods or data members of a
base class (superclass).
class ColoredSphere public Sphere public
ColoredSphere(Color initial Color)
ColoredSphere(Color initial Color, double
initialRadisu) void setColor(Color newColor)
Color getColor() const private Color c
// end ColoredSphere
You can also add new operations and
characteristics.
50Inheritance in C (2/2)
- An instance of a derived class can invoke public
methods of the base class.
void useColoredSphere() ColoredSphere
ball(RED) ball.setRadius(5.0) ...
Invoke the constructor of the derived class.
Invoke the public function of the base class.
51C Namespaces (1/4)
include ltiostream.hgt // old-style library
include ltiostreamgt using namespace std include
"Sphere.h" // header file int main() // the
client Sphere unitSphere Sphere
mySphere(5.1) cout ltlt mySphere.getDiameter()
ltlt endl . . . // end main
52C Namespaces (2/4)
- C provides a mechanism for logically grouping
related classes and other declarations, such as
functions, variables, types, and constants into a
common declarative region, known as a namespace.
namespace smallNamespace int count 0
void abc() // Place declarations here // end
smallNamespace
53C Namespaces (3/4)
- Use the scope resolution operator () to access
elements from outside the namespace. -
- smallNamespacecount 1
- smallNameSpaceabc()
- Alternatively, the using declaration allows the
names of the elements to be used directly. - using namespace smallNamespace
- count 1
- abc()
54C Namespaces (4/4)
- Items declared in the C Standard Library are
declared in the std namespace. - Input/output, file access, string, exception,
etc. - To include input and output functions from the
C library, write - include ltiostreamgt
- using namespace std
- Check appendix A.11 Libraries Appendix C for
detailed information.
55An Array-Based ADT List (1/6)
- ADT Implementation
- Choose the data structure to represent the ADTs
data. - Write functions that access the data in
accordance with the ADT operation specifications. - Data structure
- Using an array to represent a list is a natural
choice. - Both an array and a list identify their items by
number. - However, array has a fixed size, but list can
have an arbitrary length. - You need a variable to keep track the length of
the list.
56An Array-Based ADT List (2/6)
- Store a lists items in an array items.
- size to trakc the length of the list.
const int MAX_LIST 100 typedef int
ListItemType class List public . .
. private ListItemType itemsMAX_LIST
int size // end List
Chapter 1, modifiabiliy named constant typedef
statement
57An Array-Based ADT List (3/6)
- A lists kth item is stored in itemsk-1.
Figure 3-11 An array-based implementation of the
ADT list
58An Array-Based ADT List (4/6)
- To insert an item, make room in the array.
- Insertion of item 44 at position 3.
59An Array-Based ADT List (5/6)
- To delete an item at position 4.
- Remove gap in array.
Fill the gap caused by the deleted item.
60An Array-Based ADT List (6/6)
- An array that is full of gaps has the following
problems - size 1 is no longer the index of the last item
in the array. - When itemsMAX_LIST -1 is occupied, the list
could appear full, even when fewer than MAX_LIST
items are present. - Because the items are spread out, the method
retrieve might have to look every cell of the
array even when only a few items are present.
61An Array-Based ADT List ListA.h (1/4)
/ _at_file ListA.h / const int MAX_LIST
10 typedef int ListItemType class
List public / Default constructor /
List() // Destructor is supplied by
compiler // list operations / Determines
whether a list is empty. _at_pre None.
_at_post None. _at_return True if the list is
empty otherwise returns false. / bool
isEmpty() const
62An Array-Based ADT List ListA.h (2/4)
/ Determines the length of a list.
_at_pre None. _at_post None. _at_return The
number of items that are currently in the list.
/ int getLength() const / Inserts an
item into the list at position index. _at_pre
1 lt index lt getLength() 1. _at_post If
insertion is successful, newItem is at position
index in the list, and other items
are renumbered accordingly, and
success is true otherwise success is false.
_at_param index The list position at which to
insert newItem. _at_param newItem The
ListItemType to insert into the list.
_at_param success Error condition indicator. /
void insert(int index, const ListItemType
newItem, bool success)
63An Array-Based ADT List ListA.h (3/4)
/ Deletes an item from the list at a given
position. _at_pre 1 lt index lt getLength().
_at_post If 1 lt index lt getLength(), the item at
position index in the list is deleted,
other items are renumbered accordingly,
and success is true otherwise success is false.
_at_param index The list position to delete
from. _at_param success Error condition
indicator. / void remove(int index, bool
success) / Retrieves a list item by
position. _at_pre 1 lt index lt getLength().
_at_post If 1 lt index lt getLength(), dataItem is
the value of the desired item and
success is true otherwise success is false.
_at_param index The list position to retrieve
from. _at_param dataItem The ListItemType
retrieved from the list. _at_param success
Error condition indicator. / void retrieve(int
index, ListItemType dataItem, bool success)
const
64An Array-Based ADT List ListA.h (4/4)
private / array of list items /
ListItemType itemsMAX_LIST / number of
items in list / int size /
Converts the position of an item in a list to the
correct index within its array
representation. _at_pre 1 lt index lt
getLength(). _at_param index The list
position to translate. _at_return The array
index corresponding to list position index. /
int translate(int index) const // end List //
End of header file.
65An Array-Based ADT List ListA.cpp (1/4)
/ _at_file ListA.cpp / include "ListA.h" //
header file ListList() size(0) // end
default constructor bool ListisEmpty()
const return size 0 // end
isEmpty int ListgetLength() const return
size // end getLength
66An Array-Based ADT List ListA.cpp (2/4)
void Listinsert(int index, const ListItemType
newItem, bool success)
success (index gt 1) (index lt
size 1) (size lt MAX_LIST)
if (success) // make room for new item by
shifting all items at // positions gt index
toward the end of the // List (no shift if
index size 1) for (int pos size pos
gt index --pos) itemstranslate(pos
1) itemstranslate(pos) // insert new
item itemstranslate(index) newItem
size // increase the size of the list by
one // end if // end insert
67An Array-Based ADT List ListA.cpp (3/4)
void Listremove(int index, bool success)
success (index gt 1) (index lt size) if
(success) // delete item by shifting all
items at positions gt // index toward the
beginning of the list // (no shift if index
size) for (int fromPosition index
1 fromPosition lt size fromPosition)
itemstranslate(fromPosition - 1)
itemstranslate(fromPosition) --size
// decrease the size of the list by one //
end if // end remove
68An Array-Based ADT List ListA.cpp (4/4)
void Listretrieve(int index, ListItemType
dataItem, bool success)
const success (index gt 1) (index lt
size) if (success) dataItem
itemstranslate(index) // end retrieve int
Listtranslate(int index) const return
index - 1 // end translate
69Summary of ADT Implementation
- To implement an ADT
- First choose a data structure to contain the
data. - Then, implement the classs method (ADT
operations) within an implementation file. - Define and implement a class within a header
file. - ADT operations are member functions ? public.
- ADT data are data members ? private.
- Access data only by the ADT operations!!
70Summary (1/2)
- Data abstraction controls the interaction between
a program and its data structures. - Abstract data type (ADT) a set of
data-management operations together with the data
values upon which they operate. - Define an ADT fully before making any decisions
about an implementation.
71Summary (2/2)
- Hide an ADTs implementation by defining the ADT
as a C class. - Members of a class are private by default.
- Data members are typically private.
- Public methods can be provided to access them.
- Define and implement a class within header and
implementation files.
72Homework 4
- Exercises 1, 6, 18. (due date 10/29)
- For exercise 6, the rate of interest is 0.037.