CSF213 OOP ClassAndLabNotes
CSF213 OOP ClassAndLabNotes
Ramprasad S Joshi
August 2023
Abstract
We focus on practice sessions and examples or experiments that consolidate the discussions dyring lectures.
Chapter 1
Object oriented programming is not about classes and methods, or about some condensed jargon like encapsulation and
code reusability. Computational models of real-life interaction follow conceptualization of the entities involved in that
interactions, the various modes of that interaction, and the relationships, constraints and interdependence amongst the
entities that shape up the interaction patterns. This conceptualization is best done in a functional object-oriented design.
Our textbook says about itself [Blaha and Rumbaugh, 2004, pp.xv–xvi, Preface]:
Our emphasis differs from that of some in the object-oriented programming community but is in accord with the information
modeling and design methodology communities. We emphasize object-oriented constructs as models of real things, rather than as
techniques for programming. We elevate interobject relationships to the same semantic level as classes, rather than hiding them
as pointers inside objects. We place somewhat less emphasis on inheritance and methods. We downplay fine details of inheritance
mechanisms. We come down strongly in favor of typing, classes, modeling, and advance planning. We also show how to apply
object-oriented concepts to state machines.
...
There are many books on the market that cover object-oriented technology. This book differs from most in that it teaches
how to think about object-oriented modeling, rather than just presenting the mechanics of a programming language or modeling
notation.
Many of the available object-oriented books are about programming issues, often from the point of view of a single language.
Some of these books do discuss design issues, but they are still mainly about programming. Few books focus on object-oriented
analysis or design. We show that object-oriented concepts can and should be applied throughout the entire software life cycle.
In addition there are a number of books that present the concepts of the UML. This book is different than most in that it
not only explains the concepts, but it also explains their fundamental purpose and shows how to use them to build software. We
do not explain every concept and nuance, but we do strive to explain the core of UML–enough to help you learn how to use the
UML to build better software.
...
We have carried forward the first edition’s focus on “the three models” because we believe such an emphasis is helpful
for teaching and learning OO modeling. However, we dropped the functional model, because it was not as useful as we had
expected. In its place, we added the interaction model to incorporate use cases and sequence diagrams and to give a more holistic
understanding of behavior among several objects.
Our Approach We will indeed follow the textbook in the focus and emphasis described above. However, the book itself
was written for advanced undergraduates and graduates and professionals. Therefore, we will begin somewhat leisurely,
with top-down modular design, and pose real, practical questions for modeling real systems before introducing the tools,
techniques and programming language constructs required to model and implement them computationally. These tools,
techniques and constructs will appear to be necessary and enabling after we struggle without planning with the usual
programming toolchains and habits that we often resort to.
1
1.1 Some Slang for Ourselves
We will memorise some colloquial terminology that will have temporary meanings in our labs and classes this semester.
From time to time, we will align these terms with the more “standard” terms in use in textbooks and tech communities.
This section will grow as the semester proceeds.
1.1.1 Separations
We seek the following separations (among many others, of course) with specific purposes:
What How
Function Implementation
Behaviour State and Methods
Privacy, Integrity, Security Interfaces and Protocols
Events and Synchronization Message Passing and Real-time exceptions and interrupts
The Task
1. The top level: Build an application that offers a generic storage type Dictionary equipped with a retrieval mechanism
for arbitrary amounts of numbers.
2. Desirable design goals: Offer the end user a choice of data invariants. The invariants may be
• The stored data are always sorted.
• The data may be sorted on one of the pre-fixed functions on the data. e.g., Sorting them on squares, on absolute
values, or on a given polynomial value. Thus, [-2,-1,0,1,2] is sorted on the identity function f (x) = x, but on
squares f (x) = x2 or absolute values f (x) = |x| they are sorted as [0,-1,1,-2,2]. Note that this is a stable sort.
On the polynomial f (x) = ax2 + bx + c, if b2 − 4ac = 0 and b > 0 then again the sort will be [0,-1,1,-2,2].
• In general, then provide a sorting function that takes a key function and the dictionary as parameters and sorts
the dictionary elements on the key function values on each of them.
2
Module 2: The dict module
//dict.c
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<error.h>
typedef int *Dict;
Dict ConsDict(int size) {
int *p=(int*)malloc((size+2)*sizeof(int));
p[0] = 0; p[1] = size;
return p;
}
void SortDict(Dict d) {
BubbleSort(d+2,d[0]);
// Sort d[0]=actual count elements in it
}
void InsertDict(Dict d, int i) {
if(d[0]==d[1]) error(-1,0,"Dictionally full!");
d[d[0]+2]=i;
d[0]+=1;
}
void DisplayDict(Dict d) {
int i;
printf("Displaying dictionary with %d elements, size %d: ",d[0],d[1]);
for(i=2; i<d[0]+2; i++) {
printf("Element%02d=%d ",i-1,d[i]);
}
printf("\n");
}
The header file is not much :
// dict.h
typedef void *Dict;
extern Dict ConsDict(int);
extern void SortDict(Dict);
extern void DisplayDict(Dict);
extern void InsertDict(Dict,int);
Copy these code snippets into the suggested files, provide the usual bubblesort in dict.c, and compile by
$ gcc main.c dict.c
and run (the program, not from the lab) as:
$ ./a.out 5 4 2 1 3
Then you should be able to see
Displaying dictionary with 5 elements, size 5: Element01=5 Element02=4 Element03=2 Element04=1
Element05=3
Displaying dictionary with 5 elements, size 5: Element01=1 Element02=2 Element03=3 Element04=4
Element05=5
Provision for the compare functions will be made and explained tomorrow in the lab.
3
4. Separation between the application (client) view of a data structure (dictionary as seen in the main module via
dict.h) and
5. How and why C is not smoothly adaptable to object oriented design.
4
1. Make conscious choices and document them.
2. Documenting design choices includes recording the reasons for rejecting the alternatives also, for all the rejected
alternatives.
3. Do not be rigid, be ready to change the choices and code later, albeit with due reasoning and documentation.
4. Design changes should be tracked via version control. Next week we will introduce version control, and the tools
and techniques and systems to maintain it. Do not hide or forget the mistakes, in fact, remember the lessons learnt
well.
5
Chapter 2
Let us start with Blaha and Rumbaugh [2004, Chapter 3]: the Class Model. However, before we embark on the actual
modeling exercises in this particular manner, let us have a look at modeling as a part in a design cycle, a la Blaha and
Rumbaugh [2004, Chapter 2].
1. All models are false, some are useful (an oft-repeated quote in Physics attributed to all and sundry).
2. Typically, in sciences, modeling is used in order to understand and describe something after the fact of its happening
or coming into being. Like, forensics. Usually, a pattern is surmised, detected and modeled, so as to predict and
test it further.
3. This is theory-building.
4. For our purposes for this course, a model is an abstraction of something for the purpose of understanding it before
building it.
this often requires choosing the superfluous so that the essence is just uncovered.
6
2.1.1 All Models are False, Some are Useful
Blaha and Rumbaugh [2004, p.16] say:
All abstractions are incomplete and inaccurate. Reality is a seamless web. Anything we say about it, any description of it, is
an abridgement. All human words and language are abstractions–incomplete descriptions of the real world. This does not destroy
their usefulness. The purpose of an abstraction is to limit the universe so we can understand. In building models, therefore, you
must not search for absolute truth but for adequacy for some purpose. There is no single “correct” model of a situation, only
adequate and inadequate ones.
A good model captures the crucial aspects of a problem and omits the others. Most computer languages, for example, are
poor vehicles for modeling algorithms because they force the specification of implementation details that are irrelevant to the
algorithm. A model that contains extraneous detail unnecessarily limits your choice of design decisions and diverts attention from
the real issues.
Applying it to our humble Dictionary We want a data structure that can store unbounded (but reasonable) amounts
of all perceivable kinds of data and allows retrieving them efficiently.
What is essential in a Dictionary data structure that allows for much flexibility in its storage and retrieval, with
seamless and easy adaptation to any application without requiring an overhaul or construction of several types?
But this question may be premature for many. Before that, especially those who have not yet seen so many different data
types, of complex and varied layouts and formats and sizes, would like to ask:
How many element types do we need to examine and model before we can model and design an aggregate of those
elements, the desired Dictionary data structure?
Let us summarise.
• If we make storage most efficient, i.e., we just store a new element in the next available slot, then retrieval may not
be efficient. For each query or update, we may need to just search blindly through the aggregate, worst case O(n)
time when n is the number of elements stored. Imagine if our Library just dumped books onto shelves, without call
numbers and ordering and guides pasted on the shelves–what a nightmare would it be to borrow a book?
• If we want to make retrieval most efficient, we can keep an index on the stored elements: Given an element e, we
use a function Index(k) that gives (in some way) “direct access” to the element that has key k, without the need
for any comparison and search. How can we do this without requiring a search on the indices k themselves? This
question we need not solve algorithmically, at least for now. Reserve that for the Data Structures and Algorithms
course. We will simply look for a data structure that gives us such a “direct access”. But does that data structure
be the Dictionary that we are trying to model and build? Did this deteriorate into some circular modeling and
design exercise?
Actually there is no need to despair so. We look for some indexing or mapping scheme that finds the “address” of an
element (or some way to access it “directly”) given its key. i.e. We use the same Index(k) function to find a suitable
place for a new element (k, v), and to retrieve it once placed. Then both the problems above appear to be solved at once.
More importantly, we need not solve the problems by our own clever tricks nor do we need to prove the correctness and
efficiency of our solutions. That is, while designing our Dictionary abstract data structure, we need not even design for
the desired efficiency parameters.
7
Iterative Design Ideally, we would set out to design an abstract Dictionary only after extensive experience with
many concrete implementations of the as yet vague, undefined abstrat idea with varying efficiency goals, using the insights
distilled from that experience. Indeed, that is how abstraction actually happens and works. But for several reasons,
including the lack of any serious programming experience for most of the class, we will simply draw upon the received
collective wisdom. Using a telescope, or sending a Chandrayan, we obviate the need to die to see the heavens.
Three Models Blaha and Rumbaugh [2004, Chapter 2] describe three models:
The class model describes the static structure of a system in terms of classes and relationships. The state model describes the
control structure of a system in terms of events and states. The interaction model describes how individual objects collaborate to
achieve the behavior of the system as a whole. Different problems place different emphasis on the three kinds of models.
The Design
• Our Dictionary class a class that represents a collection of key-value pairs, where keys are
unique and are used to access the values.
• It provides the basic operations for accessing the key-value pairs stored in the collection,
which can be implemented by several underlying concrete storage structures. In the first
version, we continue our use of arrays.
• A Dictionary object needs the following attributes (fields):
records : Record[] An array of Records (Record will be another class, we will see soon. It needs to provide
a comparable key.)
size : available size.
length : count of records.
ordering : enum {NONE,ASC,DESC,PRIQASC,PRIQDESC,BST}. (This ordering means: none, ascending, descend-
ing, priority-queue-ascending giving the top element to be always the smallest, priority-queue-descending giving
the top always to be the largest, and binary search tree. These structures we can borrow from some standard
library if available, or leave for the implementer to implement. Each of the methods that modify the collection
in any way must consult this parameter and invoke corresponding ordering algorithm, possibly added as an
additional private method.)
8
• The Dictionary class defines the following methods:
get(int key) : Returns the value associated with the specified key in the dictionary, or null
if the key is not found.
put(Record record) : Inserts a record into the dictionary. If the key provided by the record
already exists, its corresponding record is replaced with the new record, and the old
record is returned. If the key is new, null is returned.
remove(int key) : Removes the record associated with the specified key from the dictionary,
and returns it. If the key is not found, null is returned.
size() : Returns the number of records stored in the dictionary.
isEmpty() : Returns true if the dictionary is empty, and false otherwise.
isFull() : Returns true if the dictionary is full (size==count), and false otherwise.
records() : Returns an enumeration of the records stored in the dictionary.
keys() : Returns an enumeration of the keys stored in the dictionary.
The Record Class Since we want this class to be “generic”, in the sense that we want to allow arbitrary structures to
be stored in this, we have to invoke the Dictionary instantiation from a suitable directory such that the JVM finds the
intended Record class in the classpath first.
Sample Record class It has two members, key:int and value:double. There is a data invariant to be maintained
as: key = ⌊value⌉ where ⌊.⌉ means the nearest integer as defined next. Thus,
⌊1.2⌉ = 1, ⌊1.6⌉ = 2, ⌊1.5⌉ = 2, ⌊0.5⌉ = 0, ⌊−1.2⌉ = −1, ⌊−1.6⌉ = −2, ⌊−1.5⌉ = −1, ⌊−0.5⌉ = −1.
Note the apparent inconsistency ensuring that no two numbers with a difference equal to 1 map to the same
integer. The constructor to the class and all other methods must at the end restore this data invariant
before returning. The methods of any Record class are: getKey(): int and getValue: double. If more
are provided, that can modify it, then the data invariant must be respected by them.
3. For all this, set-up your gitLab (https://gitlab.com/ accounts and fork the https://gitlab.com/cs-f2131/OOP
project. Tune your tools and development environment to your needs and style.
4. More than getting everything completed, making your own development environment and making a complete pro-
totype that builds into one executable and at least shows the methods to be invoked and what they are expected
to do in plain text, if not actually accomplishing it, is the goal for this session. Use the separation of the app main
and the Dictionary type done last time.
5. Record a log of your activities, their success/failure, and lessons drawn/learnt for future, in your gitLab account.
9
Appendices
The Appendices will collect, without any particular order or anchoring in the main text, articles relevant to the course.
These are to be used as reference material.
10
Appendix A
Java
11
Appendix B
12
Bibliography
Michael Blaha and James Rumbaugh. Object-Oriented Modeling and Design with UML. Prentice Hall/Pearson, 2nd
edition, 2004.
13