• Like
  • Save
Inheritance, polymorphisam, abstract classes and composition)
Upcoming SlideShare
Loading in...5
×
 

Inheritance, polymorphisam, abstract classes and composition)

on

  • 10,448 views

All important topics on one presentation...........

All important topics on one presentation...........

Statistics

Views

Total Views
10,448
Views on SlideShare
10,350
Embed Views
98

Actions

Likes
8
Downloads
969
Comments
2

5 Embeds 98

http://ilearnengineering.blogspot.in 44
http://ilearnengineering.blogspot.com 36
http://www.ilearnengineering.blogspot.in 16
http://www.slashdocs.com 1
http://www.techgig.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

12 of 2

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • The reusability is a key benefit of OO programming. By reusing the code the development effort is thus reduced. The time can further be spent in making the software reliable and ROBUST
  • Example: Design an application, teachers and the principal (director) in a school. First, assume that we have a class to define teachers, then we can use this class to model the principal. Because the principal is a teacher.
  • See inheritance4.h and pr15-02.cpp
  • See inheritance6.h and pr15-05.cpp
  • See pr15-04.cpp

Inheritance, polymorphisam, abstract classes and composition) Inheritance, polymorphisam, abstract classes and composition) Presentation Transcript

  • Inheritance
    • Encapsulation
    • Data Hiding
    • Inheritance
    • Polymorphism
    Reuse
    • In our daily lives we use the concept of classes divided
    • into subclasses, for example vehicles are divided into cars,
    • trucks, buses and motor cycles.
    • The principle in this sort of division is that each sub-class shares
    • some common features with the base class from which it
    • is derived, but also has its own particular features.
    Vehicle wheels engine Car wheels engine trunk Truck wheels engine trailer trunk trailer base class sub-classes or derived classes
    • A class defines the behavior of a set of objects
      • E.g., Vehicle, Animals, Books, etc.
    • There may be another set of objects that posses a specialization of this behavior
      • E.g., Cars, Jeeps, Busses, Reptiles, Notebooks etc
    • Only define the specialization while reusing the existing code.
  •  
  •  
  •  
  •  
    • A tandem bicycle is a kind of bicycle
      • Bicycle with two seats
    • A mountain bicycle is a kind of bicycle
      • Bicycle with shocks
    • A racing bicycle is a kind of bicycle
      • Lightweight aerodynamic construction
    • Tandem, mountain, and racing bicycles are specialized bicycles
    • Be able to create specialized program objects without starting from scratch
    • Inheritance is the object-oriented programming mechanism for specialization
  •  
    • Ability to define new classes of objects using existing classes as a basis
      • The new class inherits the attributes and behaviors of the parent classes
      • New class is a specialized version of the parent class
    • A natural way to reuse code
      • Programming by extension rather than reinvention
      • Object-oriented paradigm is well-suited for this style of programming
    • Terminology
      • Base class (superclass)
      • Derived class (subclass)
  • Base class Derived class Derived class Shape class Triangle class Circle class Right-angle Triangle Equilateral Triangle Isosceles Triangle
    • Specialization goes down the way.
    • Generalization goes up the way.
    Shape class Triangle class Circle class Right-angle Triangle Equilateral Triangle Isosceles Triangle Shape class Triangle class Circle class Right-angle Triangle Equilateral Triangle Isosceles Triangle
  • student print() year_group() CR print() inherits (isa) student_id, year, name dept, thesis
  •  
    • The simplest example of inheritance requires two classes: a base class and a derived class .
      • The base class OR super-class does not need any special syntax.
      • The derived class OR subclass on the other hand, must indicate that it’s derived from the base class.
    • This is done by placing a colon after the name of the derived class , followed by a keyword such as public and then the base class name .
    • class derivedClass : public baseClass {
      • private :
      • // Declarations of additional members, if needed.
      • public :
      • // Declarations of additional members, if needed.
      • }
    The derived class inherits from the base class: all public members (see later) The additional members defined can have the same name (and type) as those of the base class (as when some base members are to be redefined)
    • class Teacher{ // Base class
    • private:
    • string name;
    • int age, numOfStudents;
    • public:
    • void setName (string new_name){
    • name = new_name;
    • }
    • };
    • class Principal : public Teacher{ // Derived class
    • string school_name;
    • int numOfTeachers;
    • public:
    • void setSchool(const string & s_name){
    • school_name = s_name;
    • }
    • };
    • int main()
    • {
    • Teacher t1;
    • Principal p1;
    • p1.setName(" Principal 1");
    • t1.setName(" Teacher 1");
    • p1.setSchool(" Elementary School");
    • return 0;
    • }
    • The p1 object can also access, in addition to its own member function setSchool(), the member function from Parent (Base ), which is setName().
    • We have seen two access modes in C++ classes: public and private
      • Public members are directly accessible by users of the class
      • Private members are NOT directly accessible by users of the class, not even by inheritors
    • There is a 3 rd access mode: protected
      • Protected members are directly accessible by derived classes but not by other users
  • class Shape { protected : int width, height; public : void setDims ( int a, int b){ width=a; height=b;} }; class Rectangle: public Shape { public : int area ( ) { return (width * height); } }; class Triangle: public Shape { public : int area ( ) { return (width * height/2); } }; class Square: public Rectangle { public : void setDims ( int a){ width=a; height=a;} };
    • An object of a derived class inherits all the member data and functions of the base class.
      • Private members
    • Private members: of the base class are inherited by the derived class, but they are not visible in the derived class. The derived class may access them only through the public interface of the base class.
        • Not visible in the derived class.
        • The derived class may access them only through the public interface of the base class.
      • Protected Data members
        • Visible in the derived class.
        • The derived class may access protected members directly.
    • Some members (data or function) of the base class may not be suitable for the derived class. These members should be redefined in the derived class.
    • For example, assume that the Teacher class has a print function that prints properties of teachers on the screen. But this function is not sufficient for the class Principal, because principals have more properties to be printed. So the print function must be redefined .
    • class Teacher{ // Base class
    • private:
    • string name;
    • int age, numOfStudents;
    • public:
    • void setName (const string & new_name){
    • name = new_name;
    • }
    • void print() const ;
    • };
    • void Teacher::print() const
    • {
    • cout << &quot;Name: &quot; << name<< &quot; Age: &quot; << age
    • << endl;
    • cout << &quot;Number of Students: &quot; << numOfStudents
    • << endl;
    • }
    • class Principal : public Teacher{ // Derived class
    • string school_name;
    • int numOfTeachers;
    • public:
    • void setSchool(const string & s_name){
    • school_name = s_name;
    • }
    • void print() const;
    • };
    • void Principal::print() const
    • {
    • // We can write this only if base class has protected data members
    • //cout << &quot;Name: &quot; << name << &quot; Age: &quot; << age << endl;
    • //cout << &quot;Number of Students: &quot; << numOfStudents << endl;
    • cout << &quot;Name of the school: &quot; << school_name << endl;
    • }
    • print() function of the Principal class overrides (hides) the print() function of the Teacher class. Now the Principal class has two print() functions. The members of the base class can be accessed by using the scope operator ( :: ).
    • void Principal::print() const
    • // Print method of Principal class
    • {
    • Teacher::print();
    • // invokes the print function of the teacher class
    • cout << &quot;Name of the school: &quot; << school_name;
    • }
    • A class can have public or private members
    • Once inheritance enters the picture, other access possibilities arise for derived classes. In addition to private and public members a base class can also have protected members
    • Derived class inherits all members of base class whether public, private, or protected. Member functions of a derived class can access public and protected members of the base class, but not private members.
    • Objects of a derived class in main can access only public members of the base class.
  •  
    • class Animal
    • {
    • protected;
    • string str;
    • public:
    • Animal(const string s) : str(s) {};
    • void Display() { cout << ”Animal : ” << str << endl; }
    • };
    • class Dog : public Animal
    • {
    • public:
    • Dog(const string s) : Animal(s) {};
    • void Display() { cout << ”Dog : ” << str << endl; }
    • };
    • class Cat : public Animal
    • {
    • public:
    • Cat(const string s) : Animal(s) {};
    • void Display() { cout << ”Cat : ” << str << endl; }
    • };
    • Animal *zoo[3]; // defines an array of pointers to Animal
    • Animal animal(”Flipper”); // creates an Animal object
    • Dog dog(”Lassie”); // creates a Dog object
    • Cat cat(”Jerry”); // creates a Cat object
    • zoo[0] = &animal; // pointer zoo[0] points to animal
    • zoo[1] = &dog; // pointer zoo[0] points to animal
    • zoo[2] = &cat; // pointer zoo[0] points to animal
    • for (int i=0; i<3; i++)
    • zoo[i]->Display(); // static binding to Animal::Display()
    • Output:
    • Animal : Flipper
    • Animal : Lassy
    • Animal : Jerry
  • Animal Display() zoo[0]->Display(); zoo[1]->Display(); zoo[2]->Display(); Dog Display() Cat Display()
  •  
  • Inheritance Hierarchy for Person-derived Classes
    • In multiple inheritance, a derived class inherits members from all its base classes.
    • Example:
    • class B_class1{
    • public:
    • void setX(int);
    • // ...
    • };
    • class B_class2{
    • public:
    • void setY(int);
    • // ...
    • };
    • class D_class :
    • public B_class1, public B_class2 {
    • // ...
    • };
    • int main(){
    • D_class d;
    • d.setX(5);
    • d.setY(10);
    • }
    • Under multiple inheritance, a derived class object contains sub-objects for each of its base classes.
    • Multiple inheritance occurs when a class inherits from two or more base classes, like this:
    • class Base1{
    • public:
    • int a;
    • void fa1();
    • char *fa2(int);
    • };
    • class Base2{
    • public:
    • int a;
    • char *fa2(int, const char*);
    • int fc();
    • };
    • class Deriv : public Base1 , public Base2 {
    • public:
    • int a;
    • float fa1(float);
    • int fb1(int);
    • };
    • int main()
    • {
    • return 0;
    • }
    • In inheritance functions are not overloaded. They are overridden.
    • class Common
    • {
    • protected:
    • int cdata;
    • };
    • class Box : public Common
    • { };
    • class Contents : public Common
    • { };
    • class CerealPack : public Box, public Contents
    • {
      • Private:
      • int data;
      • void func1()
      • {
      • }
    • };
    • Both Box and Contents inherit from Common , and CerealPack inherits from both Box and Contents .
    • Recall that each object created through inheritance contains a subobject of the base class.
    • A Box object and Contents object will contain subobjects of Common ,
    • and a CerealPack object will contain subobjects of Box and Contents ,
    • so a CerealPack object will also contain two Common subobjects , one inherited via Box and one inherited via Contents.
    • This is a strange situation. There are two Sub-Objects when really there should be one.
    • You can fix this using a new keyword, virtual , when deriving Box and Contents from Common
    • class Common
    • {
    • protected:
    • int cdata;
    • };
    • class Box : virtual public Common
    • { };
    • class Contents : virtual public Common
    • { };
    • class CerealPack : public Box, public Contents
    • {
      • void func1()
      • {
      • int temp = cdata;
      • }
    • };
    • The virtual keyword tells the compiler to inherit only one subobject from a class into subsequent derived classes. That fixes the ambiguity problem, but other more complicated problems arise that are too complex to delve into here.
    • In general, you should avoid multiple inheritance, although if you have considerable experience in C++, you might find reasons to use it in unusual situations.
    • Private data
      • Slow and Reliable
      • Safety Critical Systems
    • Protected data
      • Fast, author of the derived class is responsible to maintain reliability
      • Real Time Systems
    • Private data: Slow and Reliable
    • In general, class data should be private . Public data is open to modification by any function anywhere in the program and should almost always be avoided. Protected data is open to modification by functions in any derived class. Anyone can derive one class from another and thus gain access to the base class’s protected data. It’s safer and more reliable if derived classes can’t access base class data directly.
    • Protected data: Fast, author of the derived class is responsible to maintain reliability
    • But in real-time systems , where speed is important, function calls to access private members is a time-consuming process. In such systems data may be defined as protected to make derived classes access data directly and faster.
    • class A{ // Base class
    • private:
    • int i; // safe
    • public:
    • void access(int new_i){ // public interface to access i
    • if (new_i > 0 && new_i <= 100)
    • i=new_i;
    • }
    • };
    • class B:public A{ // Derived class
    • private:
    • int k;
    • public:
    • void set(new_i, new_k) {
    • A::access(new_i); // reliable but slow
    • //…….continuation
    • }
    • };
    • class A{ // Base class
    • protected:
    • int i; // derived class can access directly
    • public:
    • :
    • };
    • class B:public A{ // Derived class
    • private:
    • int k;
    • public:
    • void set(new_i, new_k){
    • i=new_i; // fast
    • //……… continuation
    • }
    • };
    • Inheritance is a form of software reusability in which new classes are created from existing classes. The new class will inherit the properties of the base class.
    • Why inheritance ?
      • Software reusability saves time
      • Encourages the use of proven software
    • Multiple inheritance increases opportunities for name conflicts.
    • Example:
    • class B_class1{
    • public:
    • void f();
    • // ...
    • };
    • class B_class2{
    • public:
    • void f();
    • // ...
    • };
    • class D_class :
    • public B_class1, public B_class2 {
    • // no local f()
    • };
    • int main(){
    • D_class d;
    • d.f(); // error!
    • d.B_class1::f(); // ok
    • d.B_class2::f(); // ok
    • }
    • In multiple inheritance, constructors and destructors are invoked in the declaration order within the class derivation list.
    • Example:
    • class B_class1 {
    • public:
    • B_class1(){ cout << ``creating B_class1 ''; }
    • ~B_class1(){ cout << ``destroying B_class1 ''; }
    • // ...
    • };
    • class B_class2 {
    • public:
    • B_class2(){ cout << ``creating B_class2 ''; }
    • ~B_class2(){ cout << ``destroying B_class2 ''; }
    • // ...
    • };
    • class D_class : public B_class1, public B_class2{
    • public:
    • D_class(){ cout << ``creating D_class ''; }
    • ~D_class(){ cout << ``destroying D_class ''; }
    • // ...
    • };
    • int main(){
    • D_class d; // output?
    • }
    • In object-oriented language, a class can obtain the properties of another class through the mechanism of inheritance.
    • In C++, inheritance is supported by class derivation .
    • A derived class inherits the properties of its base class .
    • The class that is being inherited from is called the base class . The new class is called the derived class . The set of the base and derived class instances is called the class inheritance hierarchy .
    • A derived class inherits data members and member functions of its base class, and can also add its own list of generalization and specialization.
    • Generalization :
    • Extend the behavior of the base class. Add new member functions and/or data to derived class.
    • e.g. doResearch() for class Gradstudent .
    • Specialization :
    • Modify the behavior of the base class. Change implementations in the derived class without changing the base class interface.
    • e.g. getPaid() for class Student and Gradstudent .
    • Benefits of Class Inheritance:
    • Increase software reuse and quality
    • – Programmers can reuse the base classes instead of
    • writing new classes
    • – Using well-tested base classes helps reduce bugs in
    • software.
    • – Reduce code size.
    • Enhance software extensibility and comprehensibility
    • – Helps support more flexible and extensible architectures.
    • – Useful for modeling and classifying hierarchically
    • related domains.
    • Single Inheritance
    • – Only one base class per derived class
    • – Form an inheritance tree
    • e.g. Smalltalk, Simula, Java
    • Multiple Inheritance
    • – More than one base class per derived class
    • – Form an inheritance “Directed Acyclic
    • Graph”(DAG)
    • e.g. C++, Eiffel
    • Example:
    • class Pen {
    • public:
    • void SetLocation(int, int);
    • void SetStatus(int);
    • private:
    • int x, y, status; }; //end class declaration.
    • class ColorPen : public Pen {
    • public:
    • void SetColor(int);
    • private:
    • int color;
    • };
    • class derived_class_name : public base_class_name ;
    • In which public can be replaced by protected and private access specifier to describes the access for the inherited members.
    • Pen is the base class; ColorPen is the derived
    • class. The keyword public indicates here the
    • type of inheritance is public.
    • A derived class object consists of sub-objects of its base classes and a derived class portion.
    • Public Member
    • In public inheritance , public members from the base class are public in its derived classes.
    • Private Member
    • Private members in a base class are accessible only in the base class; they are not accessible in its derived classes.
    • Example:
    • x , y and status from Pen are not accessible in class ColorPen since they are private members of base class Pen .
    • Example:
    • class Pen {
    • public:
    • void SetLocation(int, int);
    • void SetStatus(int);
    • private:
    • int x, y, status;
    • };
    • class ColorPen : public Pen {
    • public:
    • void SetColor(int);
    • void setX(int xx){ x = xx; } // Error! x is not visible in
    • //ColorPen
    • private:
    • int color;
    • };
    • The private member x, y, status in class Pen can be accessed only by the implementors of class Pen .
    • Without inheritance, protected members in a class act the same as private members. They can be accessed only by the implementor of its own class.
    • In public inheritance, protected members are different from private members.
    • – A private member from base class is inaccessible in its derived class.
    • – A protected member from base class is accessible in its derived class by the derived class implementor.
    • Example:
    • class Pen {
    • public:
    • void SetLocation(int, int);
    • void SetStatus(int);
    • protected:
    • int x, y;
    • private:
    • int status;
    • };
    • class ColorPen : public Pen {
    • public:
    • void SetColor(int);
    • private:
    • int color;
    • };
    • void ColorPen::SetColor(){
    • x = 1; // ok: x is protected in Pen
    • y = 1; // ok: y is protected in Pen
    • status = 0; // error: status is invisible
    • color = 2; // ok: color is private in Colorpen
    • }
    • int main(){
    • ColorPen p;
    • p.x = 1; // error
    • p.y = 1; // error
    • p.status = 1; // error
    • p.color = 1; // error
    • }
    • The protected member x, y from base class can be accessed by the implementors of class Pen , and the implementors of derived class ColorPen .
    • x, y cannot be accessed by the user of class Pen , or the user of class ColorPen .
    • Note:
    • ColorPen has access to the protected members of only one Pen class object: its own Pen sub-object. ColorPen can not access the protected members of other Pen class objects.
    • Example:
    • class Pen {
    • public:
    • void SetLocation(int, int);
    • void SetStatus(int);
    • protected:
    • int x, y;
    • private:
    • int status; };
    • class ColorPen : public Pen {
    • public:
    • bool CompPosition( Pen &p ){
    • return ( x == p.x && y == p.y ); // Error!
    • } // ...
    • };
    • The access control of an inherited member can be changed in derived class through the use of using declaration .
    • Example:
    • class B_class{
    • public:
    • void SetX(int xx){ x = xx; }
    • private:
    • int x;};
    • class D_class : public B_class{
    • private:
    • using B_class::setX; // now setX() is private in D_class
    • // ...
    • };
    • int main(){
    • D_class d;
    • d.setX(5); // Can’t access, becomes private
    • }
    • An object of the derived class consists of sub-object
    • of its base classes and the derived class portion.
    • To construct an object of the derived class, objects
    • of the base classes are constructed first.
    • Example:
    • class B_class {
    • // ...
    • };
    • class D_class : public B_class{
    • // ...
    • };
    • class DD_class : public D_class{
    • // ...
    • };
    • DD_class dd;
    • In an inheritance hierarchy, constructors execute in a base class to derived class order.
    • Derived objects are constructed by the following steps:
    • 1. Allocate space for the entire object( base class members and derived class members)
    • 2. Invoke the base class constructor to initialize the base class part of the object.
    • 3. Initialize the members of derived class directed by the derived class constructor initializer
    • 4. Executing the body of the derived class constructor
    • Now in step 2, which constructor in based class will be invoked?
    • Example:
    • class B_class {
    • B_class(){ cout << ``Creating B_class '';}; // line 1
    • };
    • class D_class : public B_class{
    • public:
    • D_class(){ cout << ``constructing D_class ''; }
    • };
    • int main(){
    • D_class d; // output?
    • }
    • Question: What happens if the line 1 is removed?
    • If the base class has no constructor, then a system provided default constructor for base class is invoked when creating an object of the derived class.
    • Consider the following code. What is wrong?
    • class B_class {
    • public:
    • B_class(int xx, int yy) : x(xx), y(yy) {}
    • private:
    • int x, y;
    • };
    • class D_class : public B_class{
    • public:
    • D_class( int zz ) : z(zz) {}
    • private:
    • int z; };
    • int main(){
    • D_class d( 10 );
    • // ...
    • }
    • Solution 1:
    • Provide a default constructor to the base class B class .
    • class B_class {
    • public:
    • B_class( int xx = 0, int yy = 0 ) : x(xx), y(yy) {}
    • private:
    • int x, y;
    • };
    • class D_class : public B_class{
    • public:
    • D_class( int zz ) : z(zz) {}
    • private:
    • int z;
    • };
    • int main(){
    • D_class d( 10 );
    • }
    • Solution 2:
    • Explicitly invokes a B class constructor in D class constructor initializer.
    • class B_class {
    • public:
    • B_class(int xx, int yy) : x(xx), y(yy) {}
    • private:
    • int x, y;
    • };
    • class D_class : public B_class{
    • public:
    • D_class( int zz ) : B_class(0,0), z(zz) {} // here !
    • private:
    • int z;
    • };
    • int main(){
    • D_class d( 10 );
    • }
    • Example:
    • class Animal{
    • public:
    • Animal() : species(&quot;Animal&quot;) {}
    • Animal( string s ) : species(s) {}
    • private:
    • string species;
    • };
    • class Primate : public Animal {
    • public:
    • Primate() : Animal( &quot;Primate&quot; ), heart_cham(0) {}
    • Primate( int n ) : Animal( &quot;Primate&quot; ), heart_cham(n) {}
    • private:
    • int heart_cham;
    • };
    • class Human : public Primate {
    • public:
    • Human() : Primate(4) {}
    • // ...
    • };
    • int main(){
    • Primate Whazat(7);
    • Human Jenny;
    • // ...
    • }
    • When a derived class object is destroyed, the derived class portion is destroyed first.
    • In an inheritance hierarchy, destructors execute in a derived class to base class order, which is the reverse order of constructors.
    • Example:
    • class B_class {
    • public:
    • B_class(){ cout << ``Creating B_class ''; }
    • ~B_class(){ cout << ``Destroying B_class ''; }
    • };
    • class D_class : public B_class{
    • public:
    • D_class(){ cout << ``Creating D_class ''; }
    • ~D_class(){ cout << ``Destroying D_class ''; }
    • };
    • int main(){
    • D_class d; // Output?
    • }
    • The user defined copy constructor and operator= in derived class should explicitly invoke the copy constructor and operator= of its base class.
    • Example:
    • D_class::D_class( const D_class& x) : B_class(x){
    • // then performs copy for members of derived class ...
    • }
    • D_class& D_class::operator=( const D_class& x ){
    • B_class::operator=(x);
    • // then performs copy for members of derived class ...
    • }
    • Base class members and its derived class members belong to different class scopes.
    • The scope of the derived class can be viewed as nested within the scope of its base class.
    • The name resolution is performed before the access control is performed.
    • Example:
    • class B_class{
    • protected:
    • string x;
    • int y;
    • private:
    • int z;
    • };
    • class D_class : public B_class{
    • public:
    • void f();
    • private:
    • int x;
    • };
    • void D_class::f(){
    • x = 1; // ok
    • x = &quot;hello!&quot;; // error:
    • // x is resolved to D_class::x
    • // type mismatch
    • B_class::x = &quot;hello!&quot;; // ok
    • y = 1; // ok
    • z = 1; // error:
    • // z is resolved to B_class::z,
    • // but not accessible.
    • }
    • If the derived class adds a member with the same name of a member in the base class, the local member hides the inherited member.
    • Example:
    • class B_class{
    • public:
    • void f(){ /*...*/ }
    • };
    • class D_class : public B_class{
    • public:
    • void f(int){ /*...*/ }
    • };
    • int main(){
    • D_class x;
    • x.f();
    • }
    • Here, B class::f() and D class::f(int) are not overloaded.
    • How to overload a set of functions between base class and derived class?
    • Qualify the base class member with the class scope operator so it become visible in the derived class scope, and therefore the same named functions can be overloaded.
    • Example:
    • class B_class{
    • public:
    • void f(int);
    • void f(double);
    • };
    • class D_class : public B_class{
    • public:
    • using B_class::f;
    • void f(int);
    • };
    • The using declaration enters f(int) and f(double) of the base class into the scope of the derived class.
    • Class derivation has three types: public, protected and private.
    • class B_class{
    • //...
    • };
    • // protected inheritance
    • class D_class : protected B_class{
    • //...
    • };
    • // private inheritance
    • class D_class : B_class{ // Caution:
    • //... // inheritance is PRIVATE
    • }; // by default !!!
  • public inheritance protected inheritance private inheritance public member in base class public in derived class protected in derived class private in derived class protected member in base class protected in derived class protected in derived class private in derived class private member in base class hidden in derived class hidden in derived class hidden in derived class
    • A public derivation is also called type inheritance ; it is used to model the is-a relationship between the derived class and the base class.
    • A private derivation is also called implementation inheritance . It does not model the is-a , but the is-implemented-in-terms-of relationship between the derived class and the base class.
    • Example:
    • class List{
    • public:
    • void InsertAfter (DATATYPE &item);
    • void InsertBefore (DATATYPE &item);
    • void MakeCurrent(int);
    • void RemoveCurrent();
    • bool IsEmpty ();
    • // ...
    • protected:
    • ListNode *head;
    • ListNode *current;
    • ListNode *previous;
    • // ...
    • };
    • class CircularList : public List{
    • public:
    • void ToForward(int);
    • void ToBackward(int);
    • // ...
    • };
    • class Queue : List{
    • public:
    • void Enqueue( DATATYPE& );
    • void Dequeue();
    • bool IsEmpty();
    • void PrintQueue();
    • };
    • A CircularList is a List public inheritance .
    • CircularList supports the public interface of List and two new methods: ToForward(int) and ToBackward(int) .
    • A Queue is implemented in terms of a List private inheritance .
    • Example:
    • void Queue::Dequeue(){
    • MakeCurrent( 1 );
    • RemoveCurrent();
    • }
    • Queue supports only its own public interface: Enqueue(), Dequeue(), IsEmpty(), PrintQueue()
    • In multiple inheritance, a derived class inherits members from all its base classes.
    • Example:
    • class B_class1{
    • public:
    • void setX(int);
    • // ...
    • };
    • class B_class2{
    • public:
    • void setY(int);
    • // ...
    • };
    • class D_class :
    • public B_class1, public B_class2 {
    • // ...
    • };
    • int main(){
    • D_class d;
    • d.setX(5);
    • d.setY(10);
    • }
    • Under multiple inheritance, a derived class object contains sub-objects for each of its base classes.
    • Multiple inheritance increases opportunities for name conflicts.
    • Example:
    • class B_class1{
    • public:
    • void f();
    • // ...
    • };
    • class B_class2{
    • public:
    • void f();
    • // ...
    • };
    • class D_class :
    • public B_class1, public B_class2 {
    • // no local f()
    • };
    • int main(){
    • D_class d;
    • d.f(); // error!
    • d.B_class1::f(); // ok
    • d.B_class2::f(); // ok
    • }
    • In multiple inheritance, constructors and destructors are invoked in the declaration order within the class derivation list.
    • Example:
    • class B_class1 {
    • public:
    • B_class1(){ cout << ``creating B_class1 ''; }
    • ~B_class1(){ cout << ``destroying B_class1 ''; }
    • // ...
    • };
    • class B_class2 {
    • public:
    • B_class2(){ cout << ``creating B_class2 ''; }
    • ~B_class2(){ cout << ``destroying B_class2 ''; }
    • // ...
    • };
    • class D_class : public B_class1, public B_class2{
    • public:
    • D_class(){ cout << ``creating D_class ''; }
    • ~D_class(){ cout << ``destroying D_class ''; }
    • // ...
    • };
    • int main(){
    • D_class d; // output?
    • }
    • In C++, objects of derived class can be converted to objects of base class implicitly.
    • Example:
    • class B_class{ /* ... */ };
    • class D_class : public B_class{ /* ... */ };
    • void f(B_class x);
    • int main(){
    • D_class y;
    • f( y );
    • }
    • An object of derived class is an object of base class, but an object of base class is not an object of derived class.
    • Similarly, a base class pointer or reference can refer to an object of a derived class, but a derived class pointer or reference can not refer to a base class object.
    • Example 1:
    • B_class *bptr;
    • D_class *dptr;
    • bptr = new D_class; // ok
    • dptr = new B_class; // error
    • Example 2:
    • void f(B_class *ptr, B_class &ref);
    • void g(D_class *ptr, D_class &ref);
    • B_class b;
    • D_class d;
    • f( &b, b );
    • f( &d, d );
    • g( &b, b ); // ?
    • g( &d, d );
    • Example: a student - graduate student class hierarchy.
    • class Student{
    • public:
    • Student();
    • string name();
    • double grade();
    • private:
    • double midterm, final, assignments;
    • string name;
    • };
    • string Student::name(){
    • return name;
    • }
    • double Student::grade(){
    • // calculate grade based on midterm final and assignments
    • }
    • class GradStudent : public Student{
    • public:
    • GradStudent();
    • double grade();
    • private:
    • double thesis;
    • };
    • double GradeStudent::grade(){
    • // calculate grade based on midterm, final, assignments
    • // and THESIS
    • }
    • A function compare name takes two reference to Student objects.
    • bool compare_name( Student& s1, Student& s2 ){
    • return s1.name() < s2.name();
    • }
    • Student s1, s2;
    • GradStudent g1, g2;
    • compare_name( s1, s2 ); // ok
    • compare_name( s1, g1 ); // ok
    • compare_name( g1, g2 ); // ok
    • Since GradStudent is derived from Student , we can pass a GradStudent object to compare name() . In the function call, the Student reference is bound to the Student portion inside the GradStudent object.
    • What is the problem here?
    • bool compare_grade( Student& s1, Student& s2 ){
    • return s1.grade() < s2.grade();
    • }
    • Student s1, s2;
    • GradStudent g1, g2;
    • compare_grade( s1, s2 );
    • compare_grade( s1, g1 ); // ?
    • compare_grade( g1, g2 ); // ?
    • GradStudent class has redefined the grade() member function.
    • How can we invoke the correct version based on the actual type of object passed into the function?
    • Constructors are not inherited, even though they have public visibility.
    • However, the super reference can be used within the child's constructor to call the parent's constructor.
    • In that case, the call to parent's constructor must be the first statement. Suppose I have: class A { A(int x, int y); }; class B: public A { .... some declarations }; then I try: int s, t; B bObject(s, t);
    • you have to write : B(int s, int t) : A(s,t) { }
    • Polymorphic code : Code that behaves differently when it acts on objects of different types
    • Virtual Member Function : The C++ mechanism for achieving polymorphism
    15-
    • Consider the Animal, Cat, Dog hierarchy where each class has its own version of the member function id( ).
    • A pointer to a derived class can be assigned to a pointer to a base class
    • A base class pointer can point to derived class objects
    • Animal *pA = new Cat;
    15- Animal Cat Dog Poodle
    • class Animal{
    • public: void id(){cout << &quot;animal&quot;;}
    • }
    • class Cat : public Animal{
    • public: void id(){cout << &quot;cat&quot;;}
    • }
    • class Dog : public Animal{
    • public: void id(){cout << &quot;dog&quot;;}
    • }
    15-
    • Consider the collection of different Animal objects
    • Animal *pA[] = {new Animal, new Dog,
    • new Cat};
    • and accompanying code
    • for(int k=0; k<3; k++)
    • pA[k]->id();
    • Prints: animal animal animal , ignoring the more specific versions of id() in Dog and Cat
    15-
    • Preceding code is not polymorphic: it behaves the same way even though Animal , Dog and Cat have different types and different id() member functions
    • Polymorphic code would have printed &quot; animal dog cat&quot; instead of &quot; animal animal animal&quot;
    15-
    • The code is not polymorphic because in the expression
    • pA[k]->id()
    • the compiler sees only the type of the pointer pA[k] , which is pointer to Animal
    • Compiler does not see type of actual object pointed to, which may be Animal , or Dog , or Cat
    15-
    • Declaring a function virtual will make the compiler check the type of each object to see if it defines a more specific version of the virtual function
    15-
    • If the member functions id() are declared virtual, the code
    • Animal *pA[] = {new Animal,
    • new Dog, new Cat};
    • for(int k=0; k<3; k++)
    • pA[k]->id();
    • will print animal dog cat
    15-
    • How to declare a member function virtual:
    • class Animal{
    • public: virtual void id(){cout << &quot;animal&quot;;}
    • }
    • class Cat : public Animal{
    • public: virtual void id(){cout << &quot;cat&quot;;}
    • }
    • class Dog : public Animal{
    • public: virtual void id(){cout << &quot;dog&quot;;}
    • }
    15-
    • In pA[k]->id(), Compiler must choose which version of id() to use: There are different versions in the Animal , Dog , and Cat classes
    • Function binding is the process of determining which function definition to use for a particular function call
    • The alternatives are static and dynamic binding
    15-
    • Static binding chooses the function in the class of the base class pointer, ignoring any versions in the class of the object actually pointed to
    • Static binding is done at compile time
    • Static binding is very efficient
    15-
    • Dynamic Binding determines the function to be invoked at execution time
    • Can look at the actual class of the object pointed to and choose the most specific version of the function
    • Dynamic binding is used to bind virtual functions
    • More flexible but less efficient than static binding
    15-
    • The class D is derived from two base classes B1 , B2 :
    • class D : public B1, public B2
    • {
    • };
    15- B1 B2 D
    • Multiple inheritance may result in the same base class appearing twice in a derived class
    • This causes ambiguity, and is a reason why multiple inheritance is rarely used.
    15-
    • D3 inherits two versions of base class B
    15- B D1 D2 D3
    • Solving the problem of a multiply-inherited class:
      • When a base class is declared virtual , the compiler makes sure only one version of the class gets into any derived class
      • class D1: virtual public B
      • { };
      • class D2: virtual public B
      • { };
    15-
    • What is an Abstract Class?
    • Properties of an Abstract Class
    • Discovering Abstract Classes
    Unit 02
    • A subclass (programmer) normally has the option of whether to override the methods of a superclass or not.
    • However, there are situations where the superclass (programmer) would like to force the subclass (programmer) to override a certain method.
    • This is usually the case if there is no suitable default implementation.
    Unit 02
    • For example, consider following examples of Employee and HourlyEmployee classes.
    • An abstract class is a class that contains no objects that are not members of subclasses (derived classes)
    • For example, in real life, Animal is an abstract class: there are no animals that are not dogs, or cats, or lions…
    15-
    • Abstract classes are an organizational tool: useful in organizing inheritance hierarchies
    • Abstract classes can be used to specify an interface that must be implemented by all subclasses
    15-
    • The member functions specified in an abstract class do not have to be implemented
    • The implementation is left to the subclasses
    • In C++, an abstract class is a class with at least one abstract member function
    15-
    • In C++, a member function of a class is declared to be an abstract function by making it virtual and replacing its body with = 0 ;
    • class Animal{
    • public:
    • virtual void id()=0;
    • };
    • A virtual function with its body omitted and replaced with =0 is called a pure virtual function , or an abstract function
    15-
    • Multiple inheritance is the derivation of a new class from more than one base class
    • Multiple inheritance is useful in modeling objects that have the characteristics of several different classes
    15-
    • class Employee
    • {
    • public:
    • char name[30];
    • double payRate;
    • void getdata()
    • {
    • cout<<&quot; Enter name....&quot;;
    • cin>>name;
    • cout<<&quot; Enter payrate...&quot;;
    • cin>>payRate;
    • }
    • virtual double pay()= 0;
    • void toString()
    • {
    • cout<<&quot;Name is...&quot;<<name<<&quot; payRate is....&quot;<<payRate;
    • } };
    Unit 02 Employee class must be abstract because each type of employee has different pay rate and pay calculation is different. So we make is abstract by making the pay function as pure virtual.
  • class HourlyEmployee: Employee { private: int hours; public: void getdata(){ { Employee::getdata(); cout<<&quot; Enter number of hours worked....&quot;; cin>>hours; } void toString() { Employee::toString(); cout<<&quot; Hours worked...&quot;<<hours; } double pay() { return payRate * hours; } }; Pay() function must to be redefined
    • Clearly, if the pay method is not overridden, by mistake, the pay of the HourlyEmployee will be computed wrongly.
    • To force the subclass programmer to override this method, the method should be abstract.
    Unit 02
    • class person
    • {
    • protected:
    • char name[30];
    • public:
    • void getname() {
    • cout<<&quot; Enter the name....&quot;;
    • cin>>name; }
    • void putname()
    • { cout<<&quot; Name is....&quot;<<name;
    • }
    • virtual void getdata()=0;
    • virtual bool is_outstanding()=0;
    • };
    We are defining the class person as Abstract class because it provides interface for the class student and professor. The functions getdata() and is_outstanding() are pure virtual and needs to be redefined in each derived class This class saves the data of students and professors which are of person type. The program finds the out_standing students and professors.
    • class student:public person
    • {
    • private:
    • float gpa;
    • public:
    • void getdata()
    • {
    • person::getname();
    • cout<<&quot; Enter gpa of student...&quot;;
    • cin>>gpa;
    • }
    • bool is_outstanding() {
    • return (gpa>3.75)?true:false;
    • } };
    15- We are defining the class person as Abstract class because it provides interface for the class student and professor. The functions getdata() and is_outstanding() are pure virtual and needs to be redefined in each derived class. A student is outstanding if his GPA is more than 3.75 and getdata() fucntion calls getname() function of person class.
    • class professor:public person
    • {
    • private:
    • int no_of_pub;
    • public:
    • void getdata() {
    • person::getname();
    • cout<<&quot; Enter number of publications....&quot;;
    • cin>>no_of_pub; }
    • bool is_outstanding() {
    • return ( no_of_pub>10)?true:false;
    • }
    • };
    15- Professor class creates the getdata() function and calls the person class function getname() and number of publications. Professor is outstanding if his publications are more than 10.
    • int main()
    • {
    • person* ptr[100];
    • int n=0;
    • char choice;
    • do{
    • cout<<&quot; Enter the data for student or professor....(s/p) &quot;;
    • cin>>choice;
    • if(choice=='s')
    • ptr[n]=new student;
    • else
    • ptr[n]=new professor;
    • ptr[n]->getdata(); n++;
    • cout<<&quot; Do you want to enter more (y/n)....&quot;;
    • cin>>choice;
    • }while(choice!='n');
    15- Ptr is a pointers array of base class (person). Due to pointer it can point to derived class objects like student and professor.
    • for(int i=0; i<n; i++)
    • {
    • ptr[i]->putname();
    • if(ptr[i]->is_outstanding())
    • {
    • cout<<&quot; cha giya &quot;;
    • } else
    • cout<<&quot; Farig ha &quot;;
    • }
    • system(&quot;pause&quot;);
    • return 0;
    • }
    15- Now the array ptr has the record of students and professors. Because of pointers the dynamic binding is applied which needs the function to be defined as virtual. Because of virtual function is_outstanding() is called accordingly.
    • Suppose we wish to write a program that manipulates two-dimensional geometrical shapes, namely:
      • Squares
      • Rectangles and
      • Circles
    • Suppose further that we want each such shape to tell its name, its area and its perimeter .
    • Since each of these shapes is a type of shape, it makes sense to have a superclass, Shape , from which the others can be derived.
    • However, since the computation of area and perimeter for each of these shapes is different, the subclasses should be forced to override these methods. Thus the Shape class must be abstract .
    Unit 02
    • Moreover, since square is a special type of rectangle, we can derive it from the Rectangle class.
    • Thus, we have a two level hierarchy tree shown as follows:
    Unit 02
    • Write a class, TestEmpolyee , that has the following methods:
    • a. printPay(Employee emp) : that prints the name and salary of emp.
    • b. a main method that creates an instance of MonthlyEmployee and
    • that of HourlyEmployee , and prints them using printPay method.
    • 2. Write a class, Manager , that extends MonthlyEmployee , and has another instance variables, bonus and an instance method, setBonus . Override the pay method and update TestEmployee accordinly.
    Unit 02
    • Write a class, TestShapes , that creates an instance of each of our shape classes and prints it.
    • Suppose you wish to write an application that stores information about reading materials in a BookShop. Reading materials could be books, journals, magazines and newspapers. Identify the classes (including abstract classes, if any) that are needed for this application. Draw a class diagram for the classes and implement them.
    15-
    • Write each of the following classes:
    • A class, Person , with an instance variable, name . Write appropriate accessor and mutator methods for the class. Also write a toString method for the class.
    • Employee , that extends Person , and has: two additional instance variables, ID and payRate ; and an additional method, pay , that returns the payRate. Override the toString method accordingly.
    • Faculty , that extends Employee , and has two additional variables; officeHours of type String and teachingCourses , which is an array of Courses. Each course has course code and course title. Write appropriate accessor, mutator and toString methods for the class.
    • TestPersons , that has two methods: void printPerson(Person p) that prints its argument. And a main method that creates an instance of each of the above classes and prints it using printPerson method.
    Unit 01
    • Suppose we wish to write a program that manipulates two-dimensional geometrical shapes, namely:
      • Squares
      • Rectangles and
      • Circles
    • Suppose further that we want each such shape to tell its name, its area and its perimeter .
    • Since each of these shapes is a type of shape, it makes sense to have a superclass, Shape , from which the others can be derived.
    • However, since the computation of area and perimeter for each of these shapes is different, the subclasses should be forced to override these methods. Thus the Shape class must be abstract .
    Unit 02
    • Composition is another way to relate two classes
    • In composition, one or more members of a class are objects of another class type
    • Composition is a “ has-a ” relation between classes
    • Since constructors cannot be called like other functions (no data type), the calls to constructors of member objects will be specified in the heading of definition of class’s constructor
    • In composition, we use the member object name to invoke the functions and constructors of the object
    • Inheritance is appropriate where a class can be said to be ‘a kind of’ other class
    Car Vehicle A car is ‘a kind of’ vehicle car class can inherit from vehicle class
    • Inheritance is appropriate where a class can be said to be ‘a kind of’ other class
    Car Wheel  A wheel isn’t ‘a kind of’ car. A wheel is ‘a part of’ a car - this is dealt with by aggregation which is this week’s topic
    • Define class studentType with composition
    • class studentType { public: void setStudent(string first, string last, int sid); void print() const; studentType(string first=“”, string last=“”, int sid=0); private: personType name; int SID; };
    • Implementation of the functions of class studentType void studentType::setStudent(string first, string last, int sid) { name.setName(first, last); SID = sid; } void studentType::print() const { name.print(); cout<<“The student ID is ”<<SID<<endl; } studentType::studentType(string first, string last, int sid) :name(first, last) { SID = sid; }
    • A classification hierarchy shows how classes inherit from each other and shows the position in the hierarchy as 'a kind of' relationship.
    • i.e. An Estate car is 'a kind of' car and a car is 'a kind of' vehicle.
    • Associations also form hierarchies but they are very different from inheritance. These are described by the following terms
        • Aggregation
        • Composition
        • Part-Whole
        • A Part Of (APO) ‏
        • Has a
        • Containment
    • In this type of hierarchy, classes do not inherit from other classes but are composed of other classes
    • This means that an object of one class may have it's representation defined by other objects rather than by attributes.
    • The enclosing class does not inherit any attributes or methods from these other included classes.
    • This means that this is a relationship (association) between objects.
    • An object of the enclosing class is composed wholly or partly of objects of other classes
    • Any object that has this characteristic is know as an aggregation
    • With aggregation we sometimes have to call parametrised constructors
    • When an object is created, any contained objects must be created at the same time.
    • Some objects may not have parametrised constructors so this is easy
    • If some objects do need parameters in the constructors some mechanism is required to pass the parameter to the associated objects.
    • This is done using the colon (:) operator as shown in the following example
  • class Wheel { private: int diameter; public: Wheel(int diameter_in){ diameter = diameter_in; } int getDiameter() { return diameter; } }; class Engine { private: int cc; public: Engine(int cc_in) { cc = cc_in; } int getCC()return cc; } };
  • class Car { private: Wheel nearside_front, offside_front, nearside_rear, offside_rear; Engine engine; int passengers; public: Car(int diameter_in, int cc_in, int passengers_in); void showSelf(); };
  • Car::Car(int diameter_in, int cc_in, int passengers_in) : nearside_front(diameter_in), offside_front(diameter_in), nearside_rear(diameter_in), offside_rear(diameter_in), engine(cc_in) ‏ { passengers = passengers_in; }
  • 15-
  • HL 1. Main component / sub component Composition Aggregation &quot;contains &quot; relation &quot;has&quot; relation: Main component &quot;has&quot; a sub component as a part. 2. Association &quot;owns&quot; &quot;knows&quot; &quot;uses&quot; &quot;serves“ “ observes” etc. 3. Generalisation / specialisation Inheritance General case / Special case Super class / Sub class Base class / Derived class Base class / Inherited class &quot;is&quot; relation. An instance of derived class &quot;is&quot; an instance of base class.
  • HL Composition means same as - contains - is part of Example 1. Point can be a sub component of Circle. class Circle { public: Circle(float x0=0.0, float y0=0.0, r0=0.0); Circle(const Point &cp0, r0=0.0); private: float r; Point cp; //sub component }; Constuctor implementation on the next page. Example 2. Date can be used as a data member in class Person: class Person { public: Person(const string& name, int year, int month, int day); Person(const string& name, const Date& bd); private: string name; // sub component 1 Date birthDay; // sub component 2 };
  • HL An object can have an object as a subcomponent. In this example circles have a point as a subcomponent (representing their center point */ #include <iostream.h> //Class definition of Point class Point { public: Point(float x0=0.0, float y0=0.0); void read(); void print(); private: float x; float y; }; //Class definition of Circle class Circle{ public: Circle(float x0=0.0, float y0=0.0, float r0=0.0); Circle(const Point &cp0, float r0=0.0); void read(); void print(); private: float radius; Point centerPoint; };
  • HL //Application void main (void) { Point p(11.0, 12.0); Circle c1, c2(1.0, 2.0, 10.0), c3(p, 20.0); c1.print(); c2.print(); c3.print(); } //Member function implementations //Member functions of Point Point::Point(float x0, float y0) { x = x0; y = y0; } void Point :: read() { cout << &quot; x-coordinate: &quot;; cin >> x; cout << &quot; y-coordinate: &quot;; cin >> y; } void Point :: print() { cout << &quot;(&quot; << x << &quot;,&quot; << y << &quot;)&quot;; }
  • HL //Member functions of Circle //Constructor 1 version 1 Circle::Circle(float x0, float y0, float r0): centerPoint(x0, y0){ radius = r0; } /* Constructor 1 version 2 (Point constructor is called twice) Circle::Circle(float x0, float y0, float r0) { radius = r0; centerPoint = Point(x0, y0); } */ //Constructor 2 version 1 Circle::Circle(const Point &cp0, float r0):centerPoint(cp0){ radius = r0; } /*Constructor 2 version 2 (Point constructor is called twice) Circle::Circle(const Point &cp0, float r0) { radius = r0; centerPoint = Point(cp0); //Default copy constructor of Point } */ void Circle :: read() { cout << &quot; Enter radius : &quot;; cin >> radius; cout << &quot;Enter centerpoint :&quot;; centerPoint.read(); } void Circle :: print() { cout << &quot; The circle data is :&quot;; cout << &quot; Radius is : &quot; << radius; cout << &quot; Center point is :&quot;; centerPoint.print(); }
  • HL Memory allocation is done at the same time (as one block of memory) for the main component and for sub component, because sub component is part of the memory area of the main component. The object is created in the following phases: 1. Memory is allocated for the whole object. 2. The constructor call of sub component class that is defined in the initialisation list of main component is executed. If there is no sub component constructor call in the initialisation list, the default constructor of sub component is called. 3. The function body of main component constructor is called. This rule of order means that it is guaranteed that sub component is already constructed when constructor body on main component is executed. It also guarantees that sub components are always initialised at least with default constructor of sub component class. This is useful as you can understand thinking about the differences between defining a name member in the Person class as char *name or string name!. The implementor of the Person class needs to do many things in the former case but almost nothing in the latter case.
  • HL When an object containing a sub-component object is de-allocated, the things happen in the following order: 1.The destructor of the main component is called first. 2. The destructor of the sub-component is called next. 3. The memory area is de-allocated as a whole. The default assignment operator of the main component: If we don’t overload the assignment operator in the main component class the default assignment is used. If we have overloaded assignment for the sub-component that is used in the default assignment when sub-component part is copied. The default copy constructor of the main component: If we don’t write the copy constructor for the main component class the default copy constructor is used. If we have written copy constructor for the sub-component it is used in the default copy constructor when sub-component part is constructed.
    • Write a class, TestEmpolyee , that has the following methods:
    • a. printPay(Employee emp) : that prints the name and salary of emp.
    • b. a main method that creates an instance of MonthlyEmployee and that of HourlyEmployee , and prints them using printPay method.
    • 2. Write a class, Manager , that extends MonthlyEmployee , and has another instance variables, bonus and an instance method, setBonus . Override the pay method and update TestEmployee accordinly.
    Unit 02
    • Write a class, TestShapes , that creates an instance of each of our shape classes and prints it.
    • Suppose you wish to write an application that stores information about reading materials in a BookShop. Reading materials could be books, journals, magazines and newspapers. Identify the classes (including abstract classes, if any) that are needed for this application. Draw a class diagram for the classes and implement them.
    15-
    • Write each of the following classes:
    • A class, Person , with an instance variable, name . Write appropriate accessor and mutator methods for the class. Also write a toString method for the class.
    • Employee , that extends Person , and has: two additional instance variables, ID and payRate ; and an additional method, pay , that returns the payRate. Override the toString method accordingly.
    • Faculty , that extends Employee , and has two additional variables; officeHours of type String and teachingCourses , which is an array of Courses. Each course has course code and course title. Write appropriate accessor, mutator and toString methods for the class.
    • TestPersons , that has two methods: void printPerson(Person p) that prints its argument. And a main method that creates an instance of each of the above classes and prints it using printPerson method.
    Unit 01