Tuesday 23 October 2012

File Input and Output in C++


File Input and Output in C++
Unit 9 File Input and Output in C++
Structure
9.1 Introduction
9.2 Introduction to files and streams in C++
9.3 Character and String input and output to files
9.4 Command Line Arguments and Printer Output
9.1 Introduction
This unit has the following objectives
· To understand how file input output is handled in C++
· To learn how to pass arguments during runtime
· To learn how to handle output to printer
9.2 Introduction to files and streams in C++
File input and output in C++ is handled completely by predefined file and stream related classes. The cin and cout statements which we were using for input from keyboard and output to display screen are also predefined objects of these predefined stream classes.
The header file iostream.h is a header file containing the declarations of these classes which we have been using in all our programs. Similarly other header file fstream.h contains declarations for classes used for disk file I/O.
Let us first understand what is a stream. Streams are name given for flow of data. They are logical abstraction between user and the external device.Each stream is associated and represented through a class in C++. All streams behave in the same way even though they are connected to different devices. This capability allows same functions to be used even though devices are different. The member functions in stream classes contains definitions and procedures for handling a particular kind of data. For example ifstream class is defined for handling input from disk files. So the files in C++ are objects of a particular stream class.
The stream classes are organized in a beautiful hierarchy which is slightly complex. But overview of how they are organized will provide an excellent example of inheritance and help understand files and streams in a better way.
The following figure shows a portion of stream class hierarchy in C++ which we will be using in our programs in this unit
clip_image002
Fig. 9.1: Stream Classes in C++
As shown in the fig. 9.1 all stream classes have been inherited from the base class ios. It contains many constants and member functions common to all kind of input and output. The class istream is derived from ios class which contains all the necessary functions for handling input. Some of the functions such as get(), getline(), read and overloaded extraction (>>) operators are defined in istream class. While ostream class which is also derived from ios class is dedicated for output related functions of all kinds and contains functions such as put() and write and overloaded insertion operator (<<).
The class iostream is inherited from both istream and ostream through multiple inheritance so that other classes can inherit both the functionalities of input and output from it. Three classes istream_withassign, ostream_withassign, iostream_withassign are inherited from istream, ostream, iostream respectively which adds assignment operators to these classes.Cout is an predefined object of the class ostream_withassign class. Cin is an object of the class istream_withassign class.
The class ifstream which is inherited from both istream and fstreambase is used for input files. Similarly, class ofstream which is inherited from both ostream and fstreambase is used for output files. The class fstream inherited from both iostream and fstreambase is used for files that will perform both input and output. All the three classes for file input and output ie fstream, ifstream and ofstream are declared in the header file fstream.h. The file fstream.h also includes iostream.h, so the programs using fstream.h need not explicitly include iostream.h.
Self Assessment questions
1. cin is a predefined object of _____________ class
2. ___________ header file has to be included for file input and output.
3. cout is a predefined object of ____________ class.
9.3 Character and String input and output to files
Let us see some programs that writes and reads characters and strings to text file. To write any data to a file, you should create an object of ofstream class. The function put() is used with the object to write to the file. It however writes one character at a time. The syntax of put() function is :
objectname.put(character variable).
The following program shows the use of put() function:
#include<fstream.h>
# include<string.h>
void main()
{
ofstream outfile(“test.txt”);
char str[ ]=“hello world”;
for (int j=0;j<strlen(str);j++)
outfile.put(str[j]);
}
In the above program we have created an ofstream object named outfile. The constructor of the class is invoked and a text file named test.txt is assigned to the object outfile. A text file is created in the output directory specified in your compiler and if there is already an text file with the same name, then it is overwritten. The contents of the string str is written to the file test.txt. Please note that we have include fstream.h header file.
Since the insertion operator (<<) is overloaded in the class ostream class (ofstream is derived from ostream), it can be used along with the ofstream object to write text directly to the file. The following program shows that
#include<fstream.h>
void main()
{
ofstream outfile(“test.txt”);
outfile<<“This is my first filen”;
outfile<<“Byen”;
}
To read data from any file, you should create an object of ifstream class. The function get() and getline() is used with the object to read the file. The function get() reads one character at a time. The syntax of get() function is :
objectname.get(character variable)
where object is an object of the ifstream class and the character read is stored in the variable.
The following program reads the contents of a text file character by character and prints on the screen.
#include<fstream.h>
#include <conio.h>
void main()
{
ifstream infile("test.txt");
char ch;
clrscr();
while (infile) // infile becomes 0 when eof condition is reached
{infile.get(ch);
cout << ch;}
getch();}
In the above program, we have checked the end of file condition using the objectname itself which becomes zero when end of file is reached. Alternatively, eof() member function is used to check end of file condition. It returns non zero value when end of file is reached and returns zero while it is reading the file.
The getline() function reads line by line as shown in the following program
#include<fstream.h>
#include <conio.h>
void main()
{
ifstream infile("test.txt");
char buffer[80];
clrscr();
while (!infile.eof()) //returns nonzero value when eof condition is reached
{infile.getline(buffer,80);
cout << buffer;}
getch();}
Since the extraction operator (>>) is overloaded in the class istream class (ifstream is derived from istream), it can be used along with the ifstream object to read text. However it reads one word at a time. The following program shows that
#include<fstream.h>
#include <conio.h>
void main()
{
ifstream infile("test.txt");
char buffer[25];
clrscr();
while (infile) //infile becomes 0 when eof condition is reached
{infile>>buffer;
cout << buffer;}
getch();}
While reading files, we have assumed that the files have already been existing on the disk. However it would be wise to include checks that report in case the file you intend to read is not found on the disk. The ios class contains many such status checks. The above program has been rewritten with error check while opening the file.
#include<fstream.h>
#include <conio.h>
void main()
{
ifstream infile("test.txt");
if (!infile) // check for error while opening the file
cout<<”Cannot open file”;
else
{
char buffer[25];
clrscr();
while (infile) //infile becomes 0 when eof condition is reached
{infile>>buffer;
cout << buffer;}
}
getch();}
Self Assessment questions
1. __________ is class object is used to read data from disk files
2. ________ class object is used to write date into disk files
3. __________ functions reads data from files line by line
4. _________ function writes data into files character by character
9.4 Command Line Arguments and Printer Output
Command line arguments are useful to pass arguments to the program while running the program. These arguments can be used within the program and used. Command line arguments are used when invoking the program from DOS. In C++, like C, there are two default variables argc of type int and argv (array of strings) predefined for storing command line arguments which are usually defined as arguments to the main function. The following program shows the implementation of command line arguments and simply displays them.
//comline.cpp
# include <iostream.h>
void main(int argc, char* argv[])
{
cout<<endl<<”argc= ”<<argc;
for (int j=0;j<argc;j++)
cout<<endl<<”Argument ”<<j<<”= ”<<argv[j];
}
If you invoke the above program with the statement
C:/tc> comline sujay pawan vignesh
Then the output will be as follows
argc= 4
Argument0= c:/tc/comline.exe
Argument1= sujay
Argument2= pawan
Argument3= vignesh
As you can see in the output, the argc variable contains the argument count or number of arguments including the filename. Argv contains along with the path of the executable program, the strings passed as arguments. They can be referred by their index number.
Let us see how we can send data to printer. It is similar to sending data to a disk file seen in the last section. The program uses filenames predefined in DOS for various hardware devices. PRN or LPT1 is the filename for the printer which is connected to the first parallel port. LPT2, LPT3 so on can be used if the printer is connected to second, third parallel port respectively.
The following program prints a test message to the printer
//printtest.cpp
# include<fstream.h>
void main()
{ ofstream prnfile(“PRN”);
prnfile<<”This is a test print page”;
}
In the above program we have created a ofstream object and associated it with the printer file name PRN and then flushed the contents to the object. As you can see the code and the way we direct the contents to a stream does not differ. Whether it is sending contents to display screen or printer or disk file, the syntax remains same. That is the beauty of stream class organization hierarchy.
Self Assessment questions
1. __________ is the predefined filename assigned to printer by DOS
2. ________ variable holds the count of command line arguments.
3. ___________ object is created to send any content to printer.
Summary
Disk Input and output is handled is C++ using an hierarchy of stream classes. Files in C++ are objects of classes ifstream for input, ofstream for output and fstream for input as well as output. The class organization and inheritance enables the same syntax and methods to be used irrespective of the hardware device involved in input or output. Cin and cout are predefined objects of stream classes. These classes have several status checks for checking end of file, error conditions etc.
Terminal Questions
1. Write a program that opens a text file named sample.txt and then prints the contents to the printer.
2. Write a program that will be called as mtype.cpp which imitates the type command of the dos. The user should be able to specify the name of the text file along with mtype which is read and the contents displayed on the screen.
3. we can output text to an object of class ofstream using insertion operator << because
a. the ofstream class is a stream
b. the insertion operator works with all classes
c. we are actually outputting to cout
d. the insertion operator is overloaded in ofstream
Answers to SAQs in 9.2
1. istream_withassign
2. fstream.h
3. ostream_withassign
Answers to SAQs in 9.3
1. ifstream
2. ofstream
3. getline()
4. put()
Answers to SAQs in 9.4
1. PRN
2. argc
3. ofstream
Answers to TQs
1. //file2prn.cpp
# include<fstream.h>
void main()
{
char ch;
ifstream infile;
infile.open("sample.txt");
ofstream outfile;
outfile.open("PRN");
while(infile.get(ch))
{ outfile.put(ch);
}
}
2. //mytype.cpp
# include<fstream.h>
# include<process.h>
void main(int argc, char* argv[])
{ if (argc!=2)
{ cerr<<“nFormat: mytype filename”;
exit(-1);
}
char ch;
ifstream infile;
infile.open(arg[1]);
if (!infile)
{ cerr<<“cannot open”<<argv[1];
exit(-1);
}
while(infile)
{infile.get(ch);
cout<<ch;}
}
3. the insertion operator is overloaded in ofstream
Reference Books :
1. E. Balagurusamy, “ Object Oriented Programming with C++”, Tata McGraw-Hill, 2001
2. Robert Lafore, “Object Oriented Programming in C++”, Galgotia Publications, 1994.
3. Herbert Schildt, “The Complete Reference C++”, Tata McGraw-Hill, 2001.
4. Deitel and Deitel, “C++ How to Program”, Pearson Education, 2001
5. Let Us C++, Yashawant Kanitkar, BPB Publications
6. Practical C++ Programming , O’Reilly
7. Beginning C++, Ivor Horton
8. A First book of C++, Gary Bronson
  • 1 likes

File Input and Output in C++


File Input and Output in C++
Unit 9 File Input and Output in C++
Structure
9.1 Introduction
9.2 Introduction to files and streams in C++
9.3 Character and String input and output to files
9.4 Command Line Arguments and Printer Output
9.1 Introduction
This unit has the following objectives
· To understand how file input output is handled in C++
· To learn how to pass arguments during runtime
· To learn how to handle output to printer
9.2 Introduction to files and streams in C++
File input and output in C++ is handled completely by predefined file and stream related classes. The cin and cout statements which we were using for input from keyboard and output to display screen are also predefined objects of these predefined stream classes.
The header file iostream.h is a header file containing the declarations of these classes which we have been using in all our programs. Similarly other header file fstream.h contains declarations for classes used for disk file I/O.
Let us first understand what is a stream. Streams are name given for flow of data. They are logical abstraction between user and the external device.Each stream is associated and represented through a class in C++. All streams behave in the same way even though they are connected to different devices. This capability allows same functions to be used even though devices are different. The member functions in stream classes contains definitions and procedures for handling a particular kind of data. For example ifstream class is defined for handling input from disk files. So the files in C++ are objects of a particular stream class.
The stream classes are organized in a beautiful hierarchy which is slightly complex. But overview of how they are organized will provide an excellent example of inheritance and help understand files and streams in a better way.
The following figure shows a portion of stream class hierarchy in C++ which we will be using in our programs in this unit
clip_image002
Fig. 9.1: Stream Classes in C++
As shown in the fig. 9.1 all stream classes have been inherited from the base class ios. It contains many constants and member functions common to all kind of input and output. The class istream is derived from ios class which contains all the necessary functions for handling input. Some of the functions such as get(), getline(), read and overloaded extraction (>>) operators are defined in istream class. While ostream class which is also derived from ios class is dedicated for output related functions of all kinds and contains functions such as put() and write and overloaded insertion operator (<<).
The class iostream is inherited from both istream and ostream through multiple inheritance so that other classes can inherit both the functionalities of input and output from it. Three classes istream_withassign, ostream_withassign, iostream_withassign are inherited from istream, ostream, iostream respectively which adds assignment operators to these classes.Cout is an predefined object of the class ostream_withassign class. Cin is an object of the class istream_withassign class.
The class ifstream which is inherited from both istream and fstreambase is used for input files. Similarly, class ofstream which is inherited from both ostream and fstreambase is used for output files. The class fstream inherited from both iostream and fstreambase is used for files that will perform both input and output. All the three classes for file input and output ie fstream, ifstream and ofstream are declared in the header file fstream.h. The file fstream.h also includes iostream.h, so the programs using fstream.h need not explicitly include iostream.h.
Self Assessment questions
1. cin is a predefined object of _____________ class
2. ___________ header file has to be included for file input and output.
3. cout is a predefined object of ____________ class.
9.3 Character and String input and output to files
Let us see some programs that writes and reads characters and strings to text file. To write any data to a file, you should create an object of ofstream class. The function put() is used with the object to write to the file. It however writes one character at a time. The syntax of put() function is :
objectname.put(character variable).
The following program shows the use of put() function:
#include<fstream.h>
# include<string.h>
void main()
{
ofstream outfile(“test.txt”);
char str[ ]=“hello world”;
for (int j=0;j<strlen(str);j++)
outfile.put(str[j]);
}
In the above program we have created an ofstream object named outfile. The constructor of the class is invoked and a text file named test.txt is assigned to the object outfile. A text file is created in the output directory specified in your compiler and if there is already an text file with the same name, then it is overwritten. The contents of the string str is written to the file test.txt. Please note that we have include fstream.h header file.
Since the insertion operator (<<) is overloaded in the class ostream class (ofstream is derived from ostream), it can be used along with the ofstream object to write text directly to the file. The following program shows that
#include<fstream.h>
void main()
{
ofstream outfile(“test.txt”);
outfile<<“This is my first filen”;
outfile<<“Byen”;
}
To read data from any file, you should create an object of ifstream class. The function get() and getline() is used with the object to read the file. The function get() reads one character at a time. The syntax of get() function is :
objectname.get(character variable)
where object is an object of the ifstream class and the character read is stored in the variable.
The following program reads the contents of a text file character by character and prints on the screen.
#include<fstream.h>
#include <conio.h>
void main()
{
ifstream infile("test.txt");
char ch;
clrscr();
while (infile) // infile becomes 0 when eof condition is reached
{infile.get(ch);
cout << ch;}
getch();}
In the above program, we have checked the end of file condition using the objectname itself which becomes zero when end of file is reached. Alternatively, eof() member function is used to check end of file condition. It returns non zero value when end of file is reached and returns zero while it is reading the file.
The getline() function reads line by line as shown in the following program
#include<fstream.h>
#include <conio.h>
void main()
{
ifstream infile("test.txt");
char buffer[80];
clrscr();
while (!infile.eof()) //returns nonzero value when eof condition is reached
{infile.getline(buffer,80);
cout << buffer;}
getch();}
Since the extraction operator (>>) is overloaded in the class istream class (ifstream is derived from istream), it can be used along with the ifstream object to read text. However it reads one word at a time. The following program shows that
#include<fstream.h>
#include <conio.h>
void main()
{
ifstream infile("test.txt");
char buffer[25];
clrscr();
while (infile) //infile becomes 0 when eof condition is reached
{infile>>buffer;
cout << buffer;}
getch();}
While reading files, we have assumed that the files have already been existing on the disk. However it would be wise to include checks that report in case the file you intend to read is not found on the disk. The ios class contains many such status checks. The above program has been rewritten with error check while opening the file.
#include<fstream.h>
#include <conio.h>
void main()
{
ifstream infile("test.txt");
if (!infile) // check for error while opening the file
cout<<”Cannot open file”;
else
{
char buffer[25];
clrscr();
while (infile) //infile becomes 0 when eof condition is reached
{infile>>buffer;
cout << buffer;}
}
getch();}
Self Assessment questions
1. __________ is class object is used to read data from disk files
2. ________ class object is used to write date into disk files
3. __________ functions reads data from files line by line
4. _________ function writes data into files character by character
9.4 Command Line Arguments and Printer Output
Command line arguments are useful to pass arguments to the program while running the program. These arguments can be used within the program and used. Command line arguments are used when invoking the program from DOS. In C++, like C, there are two default variables argc of type int and argv (array of strings) predefined for storing command line arguments which are usually defined as arguments to the main function. The following program shows the implementation of command line arguments and simply displays them.
//comline.cpp
# include <iostream.h>
void main(int argc, char* argv[])
{
cout<<endl<<”argc= ”<<argc;
for (int j=0;j<argc;j++)
cout<<endl<<”Argument ”<<j<<”= ”<<argv[j];
}
If you invoke the above program with the statement
C:/tc> comline sujay pawan vignesh
Then the output will be as follows
argc= 4
Argument0= c:/tc/comline.exe
Argument1= sujay
Argument2= pawan
Argument3= vignesh
As you can see in the output, the argc variable contains the argument count or number of arguments including the filename. Argv contains along with the path of the executable program, the strings passed as arguments. They can be referred by their index number.
Let us see how we can send data to printer. It is similar to sending data to a disk file seen in the last section. The program uses filenames predefined in DOS for various hardware devices. PRN or LPT1 is the filename for the printer which is connected to the first parallel port. LPT2, LPT3 so on can be used if the printer is connected to second, third parallel port respectively.
The following program prints a test message to the printer
//printtest.cpp
# include<fstream.h>
void main()
{ ofstream prnfile(“PRN”);
prnfile<<”This is a test print page”;
}
In the above program we have created a ofstream object and associated it with the printer file name PRN and then flushed the contents to the object. As you can see the code and the way we direct the contents to a stream does not differ. Whether it is sending contents to display screen or printer or disk file, the syntax remains same. That is the beauty of stream class organization hierarchy.
Self Assessment questions
1. __________ is the predefined filename assigned to printer by DOS
2. ________ variable holds the count of command line arguments.
3. ___________ object is created to send any content to printer.
Summary
Disk Input and output is handled is C++ using an hierarchy of stream classes. Files in C++ are objects of classes ifstream for input, ofstream for output and fstream for input as well as output. The class organization and inheritance enables the same syntax and methods to be used irrespective of the hardware device involved in input or output. Cin and cout are predefined objects of stream classes. These classes have several status checks for checking end of file, error conditions etc.
Terminal Questions
1. Write a program that opens a text file named sample.txt and then prints the contents to the printer.
2. Write a program that will be called as mtype.cpp which imitates the type command of the dos. The user should be able to specify the name of the text file along with mtype which is read and the contents displayed on the screen.
3. we can output text to an object of class ofstream using insertion operator << because
a. the ofstream class is a stream
b. the insertion operator works with all classes
c. we are actually outputting to cout
d. the insertion operator is overloaded in ofstream
Answers to SAQs in 9.2
1. istream_withassign
2. fstream.h
3. ostream_withassign
Answers to SAQs in 9.3
1. ifstream
2. ofstream
3. getline()
4. put()
Answers to SAQs in 9.4
1. PRN
2. argc
3. ofstream
Answers to TQs
1. //file2prn.cpp
# include<fstream.h>
void main()
{
char ch;
ifstream infile;
infile.open("sample.txt");
ofstream outfile;
outfile.open("PRN");
while(infile.get(ch))
{ outfile.put(ch);
}
}
2. //mytype.cpp
# include<fstream.h>
# include<process.h>
void main(int argc, char* argv[])
{ if (argc!=2)
{ cerr<<“nFormat: mytype filename”;
exit(-1);
}
char ch;
ifstream infile;
infile.open(arg[1]);
if (!infile)
{ cerr<<“cannot open”<<argv[1];
exit(-1);
}
while(infile)
{infile.get(ch);
cout<<ch;}
}
3. the insertion operator is overloaded in ofstream
Reference Books :
1. E. Balagurusamy, “ Object Oriented Programming with C++”, Tata McGraw-Hill, 2001
2. Robert Lafore, “Object Oriented Programming in C++”, Galgotia Publications, 1994.
3. Herbert Schildt, “The Complete Reference C++”, Tata McGraw-Hill, 2001.
4. Deitel and Deitel, “C++ How to Program”, Pearson Education, 2001
5. Let Us C++, Yashawant Kanitkar, BPB Publications
6. Practical C++ Programming , O’Reilly
7. Beginning C++, Ivor Horton
8. A First book of C++, Gary Bronson
  • 1 likes

Multiple Inheritance, Virtual Functions And Polymorphism


Multiple Inheritance
Unit 8 Multiple Inheritance, Virtual Functions
And Polymorphism
Structure
8.1 Introduction
8.2 Introduction to Multiple Inheritance
8.3 Introduction to Virtual Functions
8.4 Introduction to Polymorphism
8.1 Introduction
This unit has the following objectives
· To understand how to implement multiple inheritance
· To understand the complexities that might arise in multiple inheritance
· To learn the concept of virtual functions and polymorphism
8.2 Introduction to Multiple Inheritance
We have learnt in the last unit the concept of inheritance. We will explore in detail the concept of multiple inheritance and the ambiguities that might arise in multiple inheritance. Multiple Inheritance is the process of inheriting a class from more than one parent class. This would be required in several instances where you would like to have the functionalities of several classes . This is also extensively used in class libraries.
The syntax for implementing multiple inheritance is similar to single inheritance. Let us suppose, there are two classes A and B, you want to derive a class C from A and B. The syntax of class definition will be as follows:
class C : public A, public B
{
};
Let us implement a program where there are two classes namely student and employee. We will derive a class manager from the above two classes and see how member functions and constructors are implemented in multiple inheritance.
//multiple.cpp
# include<iostream.h>
# include<string.h>
# include<conio.h>
class student
{ protected:
char qual[6]; // highest degree earned
int percent; // percentage score in the last degree
public:
student()
{ strcpy(qual, “”); percent=0;}
student(char ch[6], int p)
{ strcpy(qual, ch); percent=p;}
void display()
{ cout<<endl<<”Qualification”<<qual;
cout<<endl<<”Score”<<percent;
}} ;
class employee {
protected:
int empno;
char ename[25];
public:
employee()
{ empno=0;
strcpy(ename,"");
}
employee(int n, char ch[25])
{ empno=n;
strcpy(ename,ch);
}
void display()
{cout<<endl <<"Emp Code:"<<empno;
cout<<endl <<"Name:"<<ename;
}
};
class manager: public employee, public student
{
protected:
float basic;
float hra;
public:
manager():employee(),student()
{ basic=0.0; hra=0.0;}
manager(int n,char ch[25], char ch1[6], int p, float i, float j): employee(n,ch), student(ch1,p)
{ basic=i; hra=j;}
void display()
{ employee::display();
student::display();
cout<<endl <<"Basic"<<basic;
cout<<endl <<"HRA"<<hra;
}
};
void main()
{
clrscr();
manager m1(205, “pawan”, “MBA”, 80, 40000.00, 5000.00);
m1.display();
getch();
}
You can see in the above program, that the derived class constructors calls both the parent class constructors. This is because every object of the derived class has its own copy of parent data members. Therefore it is required to initialize them as well. The parent class member functions are invoked using the scope resolution operator as shown in the display function of the manager class.
The output of the above program will be
Emp Code:205
Name:pawan
Qualification MBA
Score 80
Basic 40000
HRA 5000
Even though implementation of multiple inheritance is simple, there are several type of ambiguities that might arise in its implementation. Let us suppose there are two parent classes A and B. Class C has been derived from A and B. There is a function f1() defined in both the parent classes but f1() has not been defined in the child class. When the child class object (objc) tries to access the function f1() through a statement objc.f1(), there is compiler error. This is because the statement is ambiguous because the compiler will not be able to figure out which parent’s f1() function have to be called. The ambiguity can be resolved by prefixing the parent class name followed by scope resolution operator before the function name. The following statement would resolve the ambiguity
objc.A::f1();
The above statement implies that use the function f1() of class A. Another solution would be to introduce a dummy function f1() in Class C and invoke the parent functions whichever applicable.
Another common ambiguity raised is in the case of diamond inheritance. Diamond inheritance is a situation as shown in the following diagram arises when both the parent classes have been derived from a single parent class.
image
Fig. 8.1: Diamond Inheritance
class A
{protected:
int a;};
class B : public parent
{ }
class C: public parent
{ }
class D : public B, public C
{ public:
int f1()
return a; //à ambiguous
}
Imagine the above situation where there is a parent class A with a protected data member a. Two child classes B and C are derived publicly from A. Class D is derived both from B and C publicly. The compiler complains when the grandchild class D tries to access the member a of the parent class A. This ambiguity arises because when classes B and C are derived from A, each inherits a copy of A called subobject and contains own copy of parent data. The ambiguity arises for the grandchild in resolving which copy of the child class subobject to be accessed.
The solution for this is virtual base class. By making classes B and C as virtual classes, the two classes will share a common subobject and will result in resolving the ambiguity as shown below.
class A
{protected:
int a;};
class B : virtual public A
{}
class C: virtual public A
{}
class D : public B, public C
{ public:
int f1()
return a; //only one copy of the parent
}
Self Assessment questions
1. In case of multiple inheritance, the child class has a copy of data of all the parent classes. True/False
2. The problem of diamond inheritance ambiguity is resolved by declaring the child classes as ____________
3. In multiple inheritance if the both the parent class (A and B) have same function and child class (C) does not have that function, then the which function is called
a. Class A
b. Class B
c. Have to be specified explicitly
d. No function will be called
8.3 Introduction to Virtual Functions
Virtual means existing in effect but not in reality. Virtual functions are primarily used in inheritance. Let us suppose you have a class base as shown in the following program and two classes derv1 and derv2 are publicly derived from class base. You would like to create a pointer that points to any of the derived class objects. If you create a pointer of derv1, then it can point to derv1 object only. Compiler will complain if you assign any other object is assigned to the pointer. The solution is to create a pointer to Base class.
// objectptr.cpp
# include <iostream.h>
class base
{ public:
void show()
{cout<<“base”<<endl;}};
class derv1:public base
{ public:
void show()
{cout<<“derv1”<<endl;}};
class derv2: public base
{ public:
void show()
{cout<<“derv2”<<endl;}};
void main()
{
derv1 dv1;
derv2 dv2;
base *ptr;
ptr=&dv1;
ptr->show();
ptr=&dv2;
ptr->show();
}
The output of the above program will be surprisingly:
base
base
Even though the address of derived classes is assigned to the pointer, the compiler executes the base class function. However, if the base class function is made virtual, we get the desired result. In the following program we have made the base class function show() as virtual function by prefixing with the keyword virtual.
//virtual.cpp
# include <iostream.h>
class base
{ public:
virtual void show() // virtual function
{cout<<“base”<<endl;}};
class derv1:public base
{ public:
void show()
{cout<<“derv1”<<endl;}};
class derv2: public base
{ public:
void show()
{cout<<“derv2”<<endl;}};
void main()
{
derv1 dv1;
derv2 dv2;
base *ptr;
ptr=&dv1;
ptr->show();
ptr=&dv2;
ptr->show();
}
By declaring the base class function as virtual, we now get the output as:
derv1
derv2
In the above program, depending on the contents in the pointer, the compiler decides which class function to call during runtime. This is known as late binding or dynamic binding.
Virtual functions are for just name sake and will not be executed many a times. If the virtual function has no specific role in the base but just declared for enabling the derived class objects access through pointers, the function can be declared as a pure virtual function. A pure virtual function is one which does not have any body. Virtual functions declared by equating it to zero as shown below:
virtual void show()=0;
In inheritance, many a times you would create a class just for grouping data or functionality but the class do not have any instances of its own. Such classes which does not have any objects are known as abstract classes. For example, there is a class known as employee and there are many classes derived from this class such as manager, worker etc. In the program, the employee class brings together the common data and functions to all the subclasses and to avoid coding same functionality in each and every class. Here employee class is the abstract class.
Self Assessment questions
1. Base class functions which does not have any body is known as _______
2. The process of deciding which class function to be called during runtime is known as _______________________
3. The classes which do not have any objects are known as ___________
8.4 Introduction to Polymorphism
Virtual functions in C++ are important to implement the concept of polymorphism. Polymorphism means same content but different forms. In C++, polymorphism enables the same program code calling different functions of different classes. Imagine a situation where you would like to create a class shape and derive classes such as rectangle, circle, triangle etc. Let us suppose each of the classes has a member function draw() that causes the object to be drawn on the screen. You would like to write a common code as following so that you can draw several of these shapes with same code and the shape to be drawn is decided during runtime:
Shape *ptrarr[100]
for (int j=0;j<n;j++)
Ptrarr[j]->draw();
This is an very desirable capability that completely different functions are executed by same function call. If the ptrarr is pointing to a rectangle, a rectangle is drawn. If it is pointint to circle, circle is drawn.
This is exactly what is polymorphism. However to implement this approach several conditions should be met. Firstly, all the classes rectangle, circle, triangle should be derived from a single class (Here it is shape class). Secondly, the draw() function must be declared as virtual in the base class (in the shape class).
Operator overloading is, a type of polymorphism which allows the same operators to behave differently with different datatypes/operands.
Self Assessment questions
1. A pointer to a base class can point to the objects of a derived class. True/False
2. If there is a pointer p, to the objects of a base class and it contains the address of an object of a derived class, and both classes contain a virtual member function, ding(), then the statement p->ding(); will cause the version of ding() in the ________________ class to be executed
3. Polymorphism in C++ is implemented through ________________.
Summary
Inheritance has to be implemented with care especially when it is multiple inheritance. Multiple inheritance creates ambiguity in situation where the derived class does not implement the function implemented in both the parent class and also in case of diamond inheritance. Virtual base class helps in resolving the ambiguity. Virtual functions in base class helps to implement polymorphism in C++. Abstract classes are classes without any objects.
Terminal Questions
1. A virtual base class is useful when
a. Different functions in base an derived classes have the same name
b. There are multiple paths from one derived class to another
c. The identification of a function in a base class is ambiguous
d. It makes sense to use a base class with no body
2. Imagine a publishing company markets books and CD-ROMS. Create a class called publication which stores title and price of a publication. Derive two classes: book which adds a page count and CD-ROM which adds playing time in minutes. Each of the three classes should have a getdata() and putdata() function to get its data from the user and display the data respectively. Write a main program that creates an array of pointers to publication and in a loop, ask the user for data for book or cdrom. When user has finished entering data, display all the data.
3. Virtual functions allow you to
a. Create an array of type pointer-to-base-class that can hold pointers to derived classes
b. Create functions that have no body
c. Group objects of different classes so they can all be accessed by same function code
d. Use same function call to execute member functions of objects from different classes.
Answers to SAQs in 8.2
1. True
2. Virtual Base class
3. Have to be specified explicitly
Answers to SAQs in 8.3
1. Pure virtual functions
2. Late binding or dynamic binding
3. Abstract classes
Answers to SAQs in 8.4
1. True
2. Derived
3. Virtual functions
Answers to TQs
1. The identification of a function in a base class is ambiguous
2. //publish.cpp
# include <iostream.h>
#include<conio.h>
class publication
{ protected:
char title[80];
float price;
public:
virtual void getdata()
{ cout<<endl<<”enter title”; cin>>title;
cout<<endl<<”enter price”;cin>>price;
}
virtual void putdata()
{
cout<< endl<<”Title”<<title;
cout<<endl<<”Price”<<price;
}
};
class book: public publication
{
private:
int pages;
public:
void getdata()
{ publication::getdata();
cout<<endl<<”enter number of pages”; cin>>pages;
}
void putdata()
{
publication::putdata();
cout<< endl<<”Number of pages”<<pages;
}
};
class cdrom: public publication
{
private:
float time;
public:
void getdata()
{ publication::getdata();
cout<<endl<<”enter playing time”; cin>>time;
}
void putdata()
{
publication::putdata();
cout<< endl<<”Playing time”<<time;
}
};
void main()
{
publication * ptr[10];
book* bptr;
cdrom* cptr;
char ch;
int n=0;
do
{
cout<<”Enter data for book or cdrom(b/c)”;
cin>>ch;
if (ch==’b’)
{
bptr= new book;
bptr->getdata();
ptr[n++]=bptr;
}
else
{cptr=new cdrom;
cptr->getdata();
ptr[n++]=cptr;
}
cout<<”enter another (y/n)”;
cin>>ch;
}while (ch==’y’);
for(int j=0;j<n;j++)
ptr[j]->putdata();
getch();
}
3. Use same function call to execute member functions of objects from different classes.
  • 0 likes

Introduction to UML
Unit 7 Introduction to UML
Structure
7.1 Introduction
7.2 What is UML?
7.3 Use Case Diagrams
7.3.1 Use Case
7.3.2 Actor
7.3.3 Associations
7.3.4 Includes
7.3.5 Generalization
7.3.6 Extends
7.3.7 Applications of Use Case Diagrams
Self Assessment Questions
7.4 Class Diagrams
7.4.1 Packages
7.4.2 Classes
7.4.3 Attributes
7.4.4 Operations
7.4.5 Generalization
7.4.6 Interfaces
7.4.7 Associations
7.4.8 Aggregation and Composition
7.4.9 Dependencies
Self Assessment Questions
7.5 Object Diagrams
7.6 Interaction Diagrams
7.6.1 Instances and Messages
7.6.2 Sequence Diagram
7.6.3 Collaboration Diagram
Self Assessment Questions
7.7 Activity and State Diagrams
7.7.1 Activity Diagram
7.7.2 State Diagram
Self Assessment Questions
7.8 Implementation Diagrams – Component and Deployment
7.9 Extensibility Mechanisms
7.9.1 Stereotypes
7.9.2 Tagged Values
7.9.3 Constraints
Self Assessment Questions
7.10 Summary
7.11 Terminal Questions
References and Further Reading
7.1 Introduction
Despite the fact that several advanced languages have come out of the Information Age Revolution, such as Java, C++, XML, etc., many people are still designing their code with minimal design in mind. They fall back on the IDE to do the work for them and this as far as the design goes. This may seem acceptable in the short term, but if it’s a long term, large project involving many individuals on the project, this is a recipe for disaster. Although, graphic design has been accepted in many of the other engineering fields: Mechanical, Electrical, Architectural, for some reason software design has been very slow to adopting these methods. The main reason is that most people feel it’s a lot of extra work. Some other reasons are that people feel the tools aren’t quite there yet, lack of understanding of the methodologies, too many competing methods, too much design concepts to learn. UML is an attempt to solve some of the common issues. It’s been marketed well by Rational and it is becoming widely accepted in corporations. It seems to bring together some of the best concepts in the Object-Oriented community and provide a common way for people to communicate design. It is also adopted by the Object Management Group and is quickly becoming a standard. UML is not specific to any one implementation and brings together models that have been used for years by programmers to describe their software. UML may not be perfect design methodology, but it has adapted well to the existing technologies and is what’s out there now.
Objectives
Understanding the contents of this chapter will help you to:
· Understand UML and its advantages.
· Understand Object-Oriented Analysis and Design using UML.
· Describe the various modeling diagrams of UML, i.e., their components, usage considerations, features, and advantages.
· Know the UML extensibility mechanisms.
· Design any kind of project using Object-Oriented Analysis and Design using UML.
7.2 What is UML?
UML is the Unified Modeling Language. The Unified Modeling Language was formed in attempt to unify the best (or most popular in this case) methods in Object-Oriented Analysis and Design. Those concepts come from the leaders in the field of OO: Grady Booch, James Rumbaugh and Ivar Jacobson. The different models are pulled from each of the individual methods and bring in a contribution from each one. For example, the class model is very similar to OMT or the Rumbaugh method. The Use Case Model is brought in from Ivar Jacobson and the implementation model is from Booch. Some models, such as State and Sequence, are a combination of a few methods, taking concepts from each of the methodologies and even adding some new concepts.
The heart of object-oriented problem solving is the construction of a model. The model abstracts the essential details of the underlying problem from its usually complicated real world. Several modeling tools are wrapped under the heading of the UML, which stands for Unified Modeling Language.
Let’s understand the necessity of UML, and how it applies to problem solving. “Why is UML important?” is the inevitable question to be answered. Let's look at this question from the point of view of the construction trade. Architects design buildings. Builders use the designs to create buildings. The more complicated the building, the more critical the communication between architect and builder. Blueprints are the standard graphical language that both architects and builders must learn as part of their trade. Writing software is not unlike constructing a building. The more complicated the underlying system, the more critical the communication among everyone involved in creating and deploying the software. In the past decade, the UML has emerged as the software blueprint language for analysts, designers, and programmers alike. It is now part of the software trade.
The UML gives everyone from business analyst to designer to programmer a common vocabulary to talk about software design. The UML is applicable to object-oriented problem solving. Anyone interested in learning UML must be familiar with the underlying tenet of object-oriented problem solving – it all begins with the construction of a model. A model is an abstraction of the underlying problem. The domain is the actual world from which the problem comes. Models consist of objects that interact by sending each other messages. Think of an object as "alive." Objects have things they know (attributes) and things they can do (behaviors or operations). The values of an object's attributes determine its state. Classes are the "blueprints" for objects. A class wraps attributes (data) and behaviors (methods or functions) into a single distinct entity. Objects are instances of classes.
At the center of the UML are its nine kinds of modeling diagrams, which will be discussed in detail in this unit. The diagrams are:
· Use case diagrams
· Class diagrams
· Object diagrams
· Sequence diagrams
· Collaboration diagrams
· Activity diagrams
· State diagrams
· Component diagrams
· Deployment diagrams
7.3 Use-case Diagrams
In many design processes, the use case diagram is the first that designers will work with when starting a project.  This diagram allows for the specification of high level user goals that the system must carry out.  These goals are not necessarily tasks or actions, but can be more general required functionality of the system.
7.3.1 Use Case
More formally, a use case is made up of a set of scenarios.  Each scenario is a sequence of steps that encompass an interaction between a user and a system.  The use case brings scenarios together that accomplish a specific goal of the user.
A use case can be specified by textually describing the steps required and any alternative actions at each step.  For example, the use case for searching a web for a keyword might be shown as:
1. Customer enters the keyword
2. Customer clicks the search button
3. The search is executed
4. The results are shown
Alternative: Search Failed
If the search fails at 3, then the user is redirected back to the search screen at step 1
7.3.2 Actor
The use case diagram allows a designer to graphically show these use cases and the actors that use them.  An actor is a role that a user plays in the system.  It is important to distinguish between a user and an actor (better thought of as a role).  A user of the system may play several different roles through the course of his, her or its job (since an actor may be another system).  Examples of actors are salesperson, manager, support person, and web store system.  It is possible that the same person may be a sales person and also provide support.  When creating a use case model, we are not concerned with the individuals, only the roles that they play.
7.3.3 Associations
On a use case diagram, associations are drawn between actors and use cases to show that an actor carries out a use case.  A use case can be carried out by many actors and an actor may carry out many use cases.
clip_image002
In the above diagram, the actors are shown as the stick figure shapes on the left, the use cases are the ellipses, and the associations between them are represented by the connecting lines.  The developer and the stakeholder both are responsible for specifying the system roles, but only the developer creates the model.
7.3.4 Includes
Use cases can also be related to each other with three different links.  The diagram below shows the use of the includes link.  Both invoice purchase and online purchase include the scenarios defined by purchase valuation.  In general, the includes link is to avoid repetition of scenarios in multiple use cases.
clip_image004
7.3.5 Generalization
When a use case describes a variation on another use case, use a generalization link.  In the example below, the use case limit exceeded describes a situation in which the usual scenario of online purchase is not performed.  Use cases that generalize another use case should only specify an alternative, even exceptional, scenario to the use case being generalized.  The overall goal of the use cases should be the same.
clip_image006
7.3.6 Extends
In some instances you want to describe a variation on behavior in a more controlled form.  In such instances you can define extension points in the extended use case.  In the example below, search by name is said to extend search at the name extension point.  The extends link is more controlled than the generalization link in that functionality can only be added at the extension points.
clip_image008
7.3.7 Applications of Use Case Diagrams
Use case diagrams are helpful in three areas.
· Determining features (requirements): New use cases often generate new requirements as the system is analyzed and the design takes shape.
· Communicating with clients: Their notational simplicity makes use case diagrams a good way for developers to communicate with clients.
· Generating test cases: The collection of scenarios for a use case may suggest a suite of test cases for those scenarios.
Self Assessment Questions
1. What do you mean by a use case?
2. What is the purpose of associations in a use case diagram?
7.4 Class Diagrams
The class diagram is core to object-oriented design.  It describes the types of objects in the system and the static relationships between them.
7.4.1 Packages
Packages allow you to break up a large number of objects into related groupings.  In many object oriented languages (such as Java), packages are used to provide scope and division to classes and interfaces.  In the UML, packages serve a similar, but broader purpose.
clip_image010
7.4.2 Classes
The core element of the class diagram is the class.  In an object oriented system, classes are used to represent entities within the system; entities that often relate to real world objects.
clip_image012
The Contact class above is an example of a simple class that stores location information.
Classes are divided into three sections:
· Top: The name, package and stereotype are shown in the upper section of the class.  In Visual Case, classes shown on a diagram that do not belong to the same package as the diagram are shown with their entire path name. You can optionally assign a stereotype to a class.
· Centre: The centre section contains the attributes of the class.
· Bottom: In the lower section are the operations that can be performed on the class.
7.4.3 Attributes
An attribute is a property of a class. In the example above, we are told that a Contact has an address, a city, a province, a country and a postal code. It is generally understood that when implementing the class, functionality is provided to set and retrieve the information stored in attributes. Methods to set and retrieve attribute data are often called accessor methods (also getting and setting methods) and need not be shown in your model as they are usually inferred.
The format for attributes is:
visibility name: type = defaultValue
The visibility is as follows:
-
Private
+
Public
#
Protected
~
Package
In object oriented design, it is generally preferred to keep most attributes private as the accessor methods allow you to control access to the data.  The most common exception to this preference is constants.
In addition to the name, visibility, datatype and default value, you can specify the following properties for an attribute:
· Array: you can set an attribute to be treated as an array of attributes; shown with square braces [ ] beside the name.
· Static: attributes that are static only exist once for all instances of the class. In the example above, if we set city to be static, any time we used the Contact class the city attribute would always have the same value.
· Final: if an attribute is declared final, its value cannot be changed. The attribute is a constant.
7.4.4 Operations
The operations listed in a class represent the functions or tasks that can be performed on the data in the class.
clip_image014
In the List class above, there is one attribute (a private array of Objects) and three operations.
The format for operations is:
visibility name (parameters): type
The format is very similar to that of the attribute except with the removal of a default value and the addition of parameters.
Parameters take the format:
direction name: type = default value
The direction can be one of in, out, inout or it can be unspecified.
7.4.5 Generalization
The generalization link is used between two classes to show that a class incorporates all of the attributes and operations of another, but adds to them in some way.
clip_image016
In the above diagram, we again see our Contact class, only now with two child classes.  We can say that Client and Company inherit, generalize or extend Contact. In each of Client and Company all of the attributes in Contact (address, city, etc.) exist, but with more information added. In the above situation Contact is said to be the superclass of Client and Company.
When using a generalization link, the child classes have the option to override the operations in the parent class. That is, they can include an operation that is defined in the superclass, but define a new implementation for it. 
clip_image018
Above, OntarioTaxCalculator redefines or overrides the implementation of the method in BasicTaxCalculator. Essentially, the code is different but the operation is called the same way.
Sometimes you may want to force children to override methods in a parent class.  In this case you can define the methods in the superclass as abstract. If a class has abstract operations, the class itself is considered abstract. Abstract methods and classes are shown in italics.  Not all of the operations in an abstract class have to be abstract.
clip_image020
The abstract operation calculateTaxes in AbstractTaxCalculator must be implemented in the child classes OntarioTaxCalculator and NovaScotiaTaxCalculator. Since the operations must be implemented, it is not necessary to show them in the child classes; however you may if you choose. The key is to keep your diagrams as clear as possible. In the above instance the diagram is simple and the meaning clear, however with multiple levels of inheritance and more attributes and operations, you may wish to specify all of the methods that are overridden.
7.4.6 Interfaces
Many object oriented programming languages do not allow for multiple inheritance. The interface is used to solve the limitations posed by this. For example, in the earlier class diagram Client and Company both generalize Contact but one or the other child classes may have something in common with a third class that we do not want to duplicate in multiple classes.
clip_image022
The interface Sortable is used in the above example to show that both Company and Product implement the sort operation. We can say that Company and Product implement Sortable or that they are Sortable. Because Product already generalizes Contact, we could not also allow it to generalize Sortable. Instead, we made Sortable an interface and added a realization link to show the implementation.
Interfaces are very similar to abstract classes with the exception that they do not have any attributes. As well, unlike a class, all of the operations in an interface have no implementation. The child classes Company and Product are forced to implement the sort operation in its entirety.
7.4.7 Associations
Classes can also contain references to each other. The Company class has two attributes that reference the Client class.
clip_image024
Although this is perfectly correct, it is sometimes more expressive to show the attributes as associations.
clip_image026
The above two associations have the same meaning as the attributes in the old version of the Contact class.
The first association (the top one) represents the old contactPerson attribute.  There is one contact person in a single Company.  The multiplicity of the association is one to one meaning that for every Companythere is one and only one contactPerson and for each contactPerson there is one Company.  In the bottom association there are zero or many employees for each company.  Multiplicities can be anything you specify.  Some examples are shown:
0
Zero
1
One
1..*
One or many
1..2, 10..*
One, two or ten and above but not three through nine
The arrows at the end of the associations represent their navigability.  In the above examples, the Company references Clients, but the Client class does not have any knowledge of the Company.  You can set the navigability on either, neither or both ends of your associations.  If there is no navigability shown then the navigability is unspecified.
7.4.8 Aggregation and Composition
clip_image028
The above example shows an aggregation association and a composition association.
The composition association is represented by the solid diamond. It is said that ProductGroup is composed of Products. This means that if a ProductGroup is destroyed, the Products within the group are destroyed as well.
The aggregation association is represented by the hollow diamond. PurchaseOrder is an aggregate of Products. If a PurchaseOrder is destroyed, the Products still exist.
If you have trouble remembering the difference between composition and aggregation, just think of the alphabet. Composition means destroy and the letters 'c' and 'd' are next to each other.
7.4.9 Dependencies
A dependency exists between two elements if changes to one will affect the other. If for example, a class calls an operation in another class, then a dependency exists between the two. If you change the operation, then the dependent class will have to change as well. When designing your system, the goal is to minimize dependencies.
clip_image030
To help clarify the dependencies in your design, you may wish to draw a Package Diagram.  A package diagram is essentially a class diagram with only packages and dependencies showing.  Dependencies can exist between any components in the UML however at the highest level, dependencies will exist between packages.  Within a package, the dependencies may be too numerous to specify.  That is not to say that numerous dependencies are okay.  Even within a package you want to limit the dependencies, however between packages in particular you should be strict about the number of dependencies that exist.  In general, the fewer the dependencies the more scaleable and maintainable your system will be.
Self Assessment Questions
1. What are attributes? Mention the attributes that may be specified for a class.
2. Outline the difference between aggregation and composition.
7.5 Object Diagrams
Object diagrams show instances instead of classes. They are useful for explaining small pieces with complicated relationships, especially recursive relationships.
This small class diagram shows that a university Department can contain lots of other Departments.
clip_image032
The object diagram below instantiates the class diagram, replacing it by a concrete example.
clip_image034
Each rectangle in the object diagram corresponds to a single instance. Instance names are underlined in UML diagrams. Class or instance names may be omitted from object diagrams as long as the diagram meaning is still clear.
7.6 Interaction Diagrams
Once the use cases are specified, and some of the core objects in the system are prototyped on class diagrams, we can start designing the dynamic behavior of the system.
Recall from the Use Case Diagrams sections, that a use case encompasses an interaction between a user and a system.  Typically, an interaction diagram captures the behavior of a single case by showing the collaboration of the objects in the system to accomplish the task.  These diagrams show objects in the system and the messages that are passed between them.
clip_image036
Let's start with the simple example above: a user logging onto the system.  The Logon use case can be specified by the following step:
1. Logon dialog is shown
2. User enters user name and password
3. User clicks on OK or presses the enter key
4. The user name and password are checked and approved
5. The user is allowed into the system
Alternative: Logon Failed - if at step 4 the user name and password are not approved, allow the user to try again
Now that we have a simple Use Case to work with, we can specify some of the classes involved in the interaction.
clip_image038
The LogonDialog has public methods to show and hide the window, and a private method that is called when the user presses the ok button or clicks enter. For our example (and indeed most cases) you need not specify the interface elements of the dialog.
Our design also includes a LogonManager class that will include one method that returns true if the logon is successful, false if it is not.
clip_image040
A DatabaseAccess class will allow us to run queries against our database. We can pass a query string and a ResultSet of data will be returned.
clip_image042
Now that we have prototyped the classes involved in our interaction, we can begin to make our interaction diagrams.
7.6.1 Instances and Messages
Interaction diagrams are composed mainly of instances and messages. An instance is said to be the realization of a class that is if we have a class Doctor, than the instances are Dr. Jones, Dr. Smith, etc. In an object oriented application, instances are what exist when you instantiate a class (create a new variable with the class as its datatype).
In the UML, instances are represented as rectangles with a single label formatted as:
instanceName: datatype
You can choose to name the instance or not, but the datatype should always be specified. Below the name, you can also list the attributes and their values. In Visual Case, you can map attributes from your class and enter new values specific to that instance. Attributes need only be shown when they are important and you don't have to specify and show all of the attributes of a class.
Messages represent operation calls.  That is, if an instance calls an operation in itself or another class, a message is passed.  Also, upon the completion of the operation a return message is sent back to the instance that initiated the call.
The format for message labels is:
Sequence Iteration [Guard] : name (parameters)
Sequence represents the order in which the message is called. The sequence is redundant on sequence diagrams, but required on collaboration diagrams
Iteration – an asterix (*) is shown to represent iteration if the message is called repeatedly.
Guard – an optional boolean expression (the result is either true or false) that determines if the message is called.
Name represents the operation being called.
Parameters represent the parameters on the operation being called.
7.6.2 Sequence Diagram
Sequence diagrams emphasize the order in which things happen, while collaboration diagrams give more flexibility in their layout. You can use whichever you prefer when drawing interactions, as both show the same information.
An example sequence diagram for our logon collaboration is shown:
clip_image044
Things to Note:
· The flow of time is shown from top to bottom, that is messages higher on the diagram happen before those lower down
· The blue boxes are instances of the represented classes, and the vertical bars below are timelines
· The arrows (links) are messages - operation calls and returns from operations
· The hide and show messages use guards to determine which to call.  Guards are always shown in square braces [ ] and represent constraints on the message (the message is sent only if the constraint is satisfied)
· The messages are labeled with the operation being called and parameters are shown.  You can choose to enter the parameters or not - this is dependent upon their importance to the collaboration being shown
· The sequence numbers are not shown on the messages as the sequence is intrinsic to the diagram
Asynchronous Messages
You can specify a message as asynchronous if processing can continue while the message is being executed.  In the example below, the asynchronous call does not block processing for the regular call right below.  This is useful if the operation being called is run remotely, or in another thread.
clip_image046
7.6.3 Collaboration Diagram
Collaborations are more complex to follow than sequence diagrams, but they do provide the added benefit of more flexibility in terms of spatial layout.
clip_image048
Above is our logon interaction shown as a collaboration diagram.  Notice that each message is numbered in sequence, because it is not obvious from the diagram, the order of the messages.
Lollipop Interfaces
Another advantage over the sequence diagram is that collaboration diagrams allow you to show lollipop interfaces.
clip_image050
Suppose that our DatabaseAccess class implemented an interface called Queryable.  If the logon manager only has access to the interface, we can show that the message is called through the interface by including a lollipop interface on the diagram.  The stick of the lollipop indicates that the class DatabaseAccess realizes Queryable.
Self Assessment Questions
1. What are instances and messages?
2. What are the advantages that a collaboration diagram provides over sequence diagrams?
7.7 Activity and State Diagrams
Previously we saw how interaction diagrams demonstrate the behavior of several objects when executing a single use case. When you wish to show the sequence of events on a broader scale, use activity and state diagrams.
7.7.1 Activity Diagram
An activity is the execution of a task whether it be a physical activity or the execution of code. Simply put, the activity diagram shows the sequence of activities. Like the simple flow chart, activity diagrams have support for conditional behavior, but have added support for parallel execution as well.
clip_image052
Start each activity diagram has one start (above) at which the sequence of actions begins.
clip_image054
End – each activity diagram has one finish at which the sequence of actions ends.
clip_image056
Activity activities are connected together by transitions.
Transitions are directed arrows flowing from the previous activity to the next activity. They are optionally accompanied by a textual label of the form:
[guard] label
The guard is a conditional expression that when true indicates that the transition is taken. The label is also optional and is freeform.
clip_image058
To show conditional behavior, use a branch and a merge.  As shown above, the top diamond is a branch and has only one transition flowing into it and any number of mutually exclusive transitions flowing out.  That is, the guards on the outgoing transitions must resolve themselves so that only one is followed.  The merge is used to end the conditional behavior.  There can be any number of incoming, and only one outgoing transition.
clip_image060
To show parallel behavior, use a fork and a join, as shown above.  The fork (top) has one transition entering and any number of transitions exiting, all of which will be taken. The join (bottom) represents the end of the parallel behavior and has any number of transitions entering, and only one leaving.
Activity diagrams can be divided into object swimlanes that determine which object is responsible for which activity.
For our example, we used the following process: "Withdraw money from a bank account through an ATM." The three involved classes (people, etc.) of the activity are Customer, ATM, and Bank. The process begins at the black start circle at the top and ends at the concentric white/black stop circles at the bottom. The activities are rounded rectangles.
clip_image062
7.7.2 State Diagram
The state diagram shows the change of an object through time. Based upon events that occur, the state diagram shows how the object changes from start to finish.
clip_image064
States are represented as a rounded rectangle with the name of the state shown. Optionally you can include an activity that represents a longer running task during that state.
Connecting states together are transitions. These represent the events that cause the object to change from one state to another. The guard clause of the label is again mutually exclusive and must resolve itself to be either true or false. Actions represent tasks that run causing the transitions.
Actions are different from activities in that actions cannot be interrupted, while an activity can be interrupted by an incoming event. Both ultimately represent an operation on the object being studied. For example, an operation that sets an attribute would be considered an action, while a long calculation might be an activity. The specific separation between the two depends on the object and the system being studied.
Like activity diagrams, state diagrams have one start and one end from at which the state transitions start and end respectively.
Our example diagram models the login part of an online banking system. Logging in consists of entering a valid social security number and personal id number, then submitting the information for validation. Logging in can be factored into four non-overlapping states: Getting SSN, Getting PIN, Validating, and Rejecting. From each state comes a complete set of transitions that determine the subsequent state.
clip_image066
The action that occurs as a result of an event or condition is expressed in the form /action. While in its Validating state, the object does not wait for an outside event to trigger a transition. Instead, it performs an activity. The result of that activity determines its subsequent state.
Self Assessment Questions
1. When is it considered appropriate to use state or activity diagrams?
2. How do you show parallel behavior in an activity diagram?
7.8 Implementation Diagrams – Component and Deployment
So far, we've seen how to diagram the tasks that your system will perform the details of the classes in your system, and the dynamic behavior of the system – but what about the big picture? The two types of implementation diagrams provide the solution. With the deployment diagram, you can show how the components of your system are physically related, and with the component diagram, you can show the components in the system are organized.
A component is a code module. Component diagrams are physical analogs of class diagram. Deployment diagrams show the physical configurations of software and hardware.
You can combine the two diagrams if you choose:
clip_image068
Above, the nodes are shown as cuboids and the components are figures shown within these cuboid-shaped figures. The nodes represent something upon which a component can run, and components are units of software.
On the diagram, nodes are connected with connections that show the physical path of information in the system. Components are connected with directed dashed lines that represent the communication between components. You can also use lollipop interfaces on components to show that communication is through an interface.
7.9 Extensibility Mechanisms
The extensibility mechanisms allow you to customize and extend the UML by adding new building blocks, creating new properties, and specifying new semantics in order to make the language suitable for your specific problem domain. There are three common extensibility mechanisms that are defined by the UML: stereotypes, tagged values, and constraints.
7.9.1 Stereotypes
Stereotypes allow you to extend the vocabulary of the UML so that you can create new model elements, derived from existing ones, but that have specific properties that are suitable for your problem domain. They are used for classifying or marking the UML building blocks in order to introduce new building blocks that speak the language of your domain and that look like primitive, or basic, model elements.
For example, when modeling a network you might need to have symbols for representing routers and hubs. By using stereotyped nodes you can make these things appear as primitive building blocks.
As another example, let us consider exception classes in Java or C++, which you might sometimes have to model. Ideally you would only want to allow them to be thrown and caught, nothing else. Now, by marking them with a suitable stereotype you can make these classes into first class citizens in your model; in other words, you make them appear as basic building blocks.
Stereotypes also allow you to introduce new graphical symbols for providing visual cues to the models that speak the vocabulary of your specific domain, as shown below.
clip_image070
Graphically, a stereotype is rendered as a name enclosed by guillemots and placed above the name of another element.
clip_image072
Alternatively, you can render the stereotyped element by using a new icon associated with that stereotype.
clip_image074
7.9.2 Tagged Values
Tagged values are properties for specifying keyword-value pairs of model elements, where the keywords are attributes. They allow you to extend the properties of a UML building block so that you create new information in the specification of that element. Tagged values can be defined for existing model elements, or for individual stereotypes, so that everything with that stereotype has that tagged value. It is important to mention that a tagged value is not equal to a class attribute. Instead, you can regard a tagged value as being a metadata, since its value applies to the element itself and not to its instances.
One of the most common uses of a tagged value is to specify properties that are relevant to code generation or configuration management. So, for example, you can make use of a tagged value in order to specify the programming language to which you map a particular class, or you can use it to denote the author and the version of a component.
As another example of where tagged values can be useful, consider the release team of a project, which is responsible for assembling, testing, and deploying releases. In such a case it might be feasible to keep track of the version number and test results for each main subsystem, and so one way of adding this information to the models is to use tagged values.
Graphically, a tagged value is rendered as a string enclosed by brackets, which is placed below the name of another model element. The string consists of a name (the tag), a separator (the symbol =), and a value (of the tag), as shown below.
clip_image076
7.9.3 Constraints
Constraints are properties for specifying semantics and/or conditions that must be held true at all times for the elements of a model. They allow you to extend the semantics of a UML building block by adding new rules, or modifying existing ones.
For example, when modeling hard real time systems it could be useful to adorn the models with some additional information, such as time budgets and deadlines. By making use of constraints these timing requirements can easily be captured.
Graphically, a constraint is rendered as a string enclosed by brackets, which is placed near the associated element(s), or connected to the element(s) by dependency relationships. This notation can also be used to adorn a model element’s basic notation, in order to visualize parts of an element’s specification that have no graphical cue.
For example, you can use constraint notation to provide some properties of associations, such as order and changeability. Refer to the diagram below to understand the use of constraints.
clip_image079
Self Assessment Questions
1. What is the purpose of extensibility mechanisms in UML?
2. Describe the ways in which a stereotype may be rendered.
7.10 Summary
When starting a use case model, it is very important to keep it simple. Often it is easiest to first determine the actors of the system, and then flush out the use cases that they perform. Your use case diagrams can be as simple or complex as you wish, however simpler, less cluttered diagrams are easier to understand, and are often more powerful in capturing the tasks of the system. Remember that a use case represents a goal of a user, not an atomic programming operation. Your use case design should be simple and help to clarify the user's goals and expectations for the system.
Class diagrams really are the core of most object oriented design so you will likely find yourself using them all the time.  Fortunately class diagrams closely relate to the most object oriented languages, so the basics (classes, operations, attributes, generalizations, etc.) should be fairly easy to grasp.  Start with what you know and then move on.
Keeping your designs simple will allow you to be more productive as well as making your designs far more understandable and useable.  Also, as the system is implemented and upgraded, you'll want to keep your design in synch with your implementation.  This will be far easier with a simple design of the key concepts of the system.
Using interaction diagrams, we can clarify the sequence of operation calls among objects used to complete a single use case. When drawing these diagrams, try to keep them as clear and simple as possible. Sequence diagrams are easy to read and follow, as they enforce a standard layout on the diagram. Collaborations have the added advantage of interfaces and freedom of layout, but can be difficult to follow, understand and create. It's also important not to confuse interaction diagrams with state and activity diagrams. Interaction diagrams are used to diagram a single use case. When you want to examine the behavior of a single instance over time use a state diagram, and if you want to look at the behavior of the system over time use an activity diagram.
Activity diagrams are used to show workflow in parallel and conditionally. They are useful when working out the order and concurrency of a sequential algorithm, when analyzing the steps in a business process and when working with threads. State diagrams show the change of an object over time and are useful when an object exhibits interesting or unusual behavior - such as that of a user interface component. As always, use these diagrams only when they serve a purpose. Don't feel that you have to draw a state diagram for every object in your system and an activity diagram for every process. Use them where they add to your design. You may not even include these diagrams in your design, and your work may still be complete and useful.
The physical diagrams will help with the overall structure and distribution of your system. You can draw component and deployment diagrams separately or combine them as you choose. Also, you need not show the components within the nodes as above, although it helps in the overall understanding of what is executed where.
Modeling is all about communication. When using the UML you are provided with all the tools you need in order to specify, visualize, construct, and document the elements of a software-intensive system. However, there will be circumstances where you might want to color outside the lines, i.e. bend or extend the modeling language in order to shape and grow it to the specific needs of your project.
Don't get bogged down with semantics and detail. The UML is a very rich and detailed language; remember that you don't have to master every iota of information at first.  Get comfortable with the basics first. Similarly, keep your diagrams simple. Each diagram should have one key concept or design feature that you're trying to explain. Further, that key concept or feature should be interesting. You don't need to design the obvious, and you don't need to be redundant.  Express what needs to be expressed and move on.
7.11 Terminal Questions
1. Why is UML important?
2. Name the modeling diagrams available in UML.
3. What are the components that may be seen in a use case diagram?
4. Describe generalization with respect to a use case diagram.
5. What are the applications of use case diagrams?
6. What is a package?
7. Name the components of a class.
8. Many object oriented programming languages do not allow multiple inheritance. How can this situation be countered?
9. Describe package diagrams.
10. How are object diagrams different from class diagrams?
11. Name the types of interaction diagrams and describe them.
12. Describe the modeling components found in an activity diagram.
13. Draw a state diagram to show gear transmission in a car.
14. Compare component and deployment diagrams.
15. Describe the extensibility mechanisms of UML.
References and Further Reading
1. http://www.visualcase.com/tutorials/uml-tutorial.htm
2. http://dn.codegear.com/article/31863
3. http://www.cs.ucl.ac.uk/staff/ucacwxe/lectures/3C05-02-03/aswe
15-essay.pdf
  • 0 likes