Inheritance is a mechanism by which a new class acquires all the nonprivate features of an existing class. This mechanism is provided by object-oriented programming languages. The existing class is known as the parent class, the base class, or the super class. The new class being defined, which inherits the nonprivate features of the base class, is known as the derived class or subclass.
The new class acquires all the features of the existing base class, which is a more general class. This new class can be tailored in several ways by the programmer by adding more features or modifying some of the inherited features.
The main advantage of inheritance is that the definition and development of a class takes much less time than if the class were developed from scratch. Another advantage of inheritance is that it enhances class reuse. A subclass can be:
An extension of the base class, if it includes its own attributes and operations, in addition to the derived characteristics it inherits from the base class
A specialized version of the base class, if it overrides (redefines) one or more of the characteristics inherited from its parent class
A combination of an extension and a specialization of the base class
When a class inherits the characteristics from more than one parent class, the mechanism is called multiple inheritance. Most object-oriented programming languages support multiple inheritance; however, Java and KJP support only single inheritance. Therefore, in modeling, it is useful to show this in the class diagrams.
In UML terminology, generalization is the association between a general class and a more specialized class or extended class. This association is also known as inheritance, and it is an important relationship between classes. In the UML class diagram, the arrow that represents this relationship points from a class (the derived class) to its parent class.
Figure 12.1 illustrates a simple class hierarchy with inheritance. The parent class is Polygon and the subclasses are: Triangle, Rectangle, and Parallelogram that inherit the features from the parent class. The idea of a subclass and a subtype is important. All objects of class Parallelogram are also objects of class Polygon, because this is the base class for the other classes. On the contrary, not all objects of class Polygon are objects of class Parallelogram.
In KJP and in Java, the subclass acquires all the public and protected features of the base class. A protected feature is only accessible to the class that defines it and to the subclasses. The only public features that are not inherited by the subclasses are the initializer functions of the base classes.
In KJP, the definition of a subclass must include the keyword inherits to name the base class that it inherits. The general structure of the KJP statement that defines a subclass is:
description ... class 〈 class_name 〉 inherits 〈 base_class_name 〉 is private ... protected ... public ... endclass 〈 class_name 〉
Because a subclass can also be inherited by another class, it often includes protected features in addition to the private and public ones. In UML class diagrams, a feature of the class is indicated with a plus (+) sign if it is public, with a minus (-) sign if it is private, and with a pound (#) sign if it is protected.
An initializer function of the subclass will normally need to invoke the initializer function of the base class. The special name given to the initializer function of the base class is super. This call must be the first statement in the initializer function of the subclass. Calling this function may require arguments, and these must correspond to the parameters defined in the initializer function of the base class.
Caution | Initializer (constructor) functions are not inherited. A derived class must provide its own initializer functions. These are the only public features that are not inherited by the subclass. |
The KJP statement to call or invoke an initializer function of the base class from the subclass is:
call super 〈 using argument_list 〉
If the argument list is absent in the call, the initializer function invoked is the default initializer of the base class.
Suppose a new class, Toyball, is being defined that inherits the features of an existing (base) class Ball. The attributes of class Ball are color and size. The color attribute is coded as integer values (white is 0, blue is 2, yellow is 3, red is 4, black is 5). Class Ball includes an initializer function that sets initial values to these two attributes.
The subclass Toyball has one other attribute, weight. The initializer function of this class needs to set initial values to the three attributes, two attributes of the base class and the one attribute of the subclass. The two attributes of the base class (Ball) are set by invoking the function super in the initializer function of the subclass, Toyball.
class Toyball inherits Ball is private // attributes variables real weight // no private methods in this class public // public methods description This is the constructor, it initializes an object on creation. */ function initializer parameters real iweight, integer icolor, real isize is begin // call the initializer of the base class call super using icolor, isize set weight = iweight endfun initializer . . . endclass Toyball
The attributes of a class are private, so the only way to set the initial values for the attributes of base class is to invoke its initializer function of the base class. In the previous KJP code, this is accomplished with the statement:
call super using icolor, isize
Consider revising the employee salary problem presented in previous chapters. The problem consists of three classes, as seen in Figure 12.2.
Figure 12.2: An inheritance diagram for the Employee problem.
The base class, Person, has the basic and general characteristics of the objects in the problem. The subclass, Employeec, inherits the features of the base class and is an extension of the base class by adding two new attributes, salary and years_service, and several new functions. This class computes the salary increase for employee objects. If the object's salary is greater than $45,000.00, the salary increase is 4.5%; otherwise, the salary increase is 5%.
On the CD | The code for the KJP implementation of base class Person follows; this is stored in the file Person.kpl. |
description This is the complete definition of class Person. The attributes are age and name. */ class Person is private // attributes variables // variable data declarations integer age string obj_name // no private methods in this class public description This is the default initializer method. */ function initializer is begin set age = 21 set obj_name = "None" endfun initializer // description This is a complete initializer function, it sets the attributes to the values given on object creation. */ function initializer parameters integer iage, string iname is begin set age = iage set obj_name = iname endfun initializer description This accessor function returns the name of the object. */ function get_name of type string is begin return obj_name endfun get_name description This mutator function changes the name of the object to the name in 'new_name'. This function is void. */ function change_name parameters string new_name is begin set obj_name = new_name endfun change_name description This function returns the age of the Person object. */ function get_age of type integer is begin return age endfun get_age description This mutator function increases the age of the person object when called. */ function increase_age is begin increment age endfun increase_age endclass Person
The following KJP code implements class Employeec, which is a subclass of class Person. Class Employeec computes the salary increase.
description This class computes the salary increase for an employee. If his/her salary is greater than $45,000, the salary increase is 4.5%; otherwise, the salary increase is 5%. This is the class for employees. The main attributes are salary, age, and name. */ class Employeec inherits Person is private variables integer years_service real salary public description This is the initializer function (constructor), it initializes an object on creation. */ function initializer parameters real isalary, integer iage, string iname is begin // call the initializer in the base class call super using iage, iname set salary = isalary set years_service = 0 endfun initializer description This function gets the salary of the employee object. */ function get_salary of type real is begin return salary endfun get_salary description This accessor function gets the years of service of the employee object. */ function get_years_serv of type integer is begin return years_service endfun get_years_serv description This mutator function changes the years of service of the object by adding change_y to current years. This function is void. */ function change_yearsv parameters integer change_y is begin add change_y to years_service endfun change_yearsv description This function changes the salary of the Employee object by adding change to current salary. */ function change_sal parameters real change is begin add change to salary endfun change_sal description This function computes the salary increase and updates the salary of an employee. It returns the increase. */ function sal_increase of type real is // constant data declarations constants // percentages of salary increase real percentl = 0.045 real percent2 = 0.05 variables real increase begin // body of function starts here if salary > 45000 then set increase = salary * percent1 else set increase = salary * percent2 endif add increase to salary // update salary return increase endfun sal_increase endclass Employeec
On the CD | Class Employee is stored in file Employeec.kpl. Class Memployeec includes the definition of function main, which creates and manipulates objects of class Employeec. This class is stored in the file Memployeec.kpl and the KJP implementation is: |
import Conio // Library class for console I/O description This program computes the salary increase for an employee. This class creates and manipulates objects of class Employeec. */ class Memployeec is public description The main function of the application. */ function main is variables integer obj_age real increase real obj_salary string obj_name objects object emp_obj of class Employeec begin display "Enter name: " read obj_name display "Enter age: " read obj_age display "Enter salary: " read obj_salary create emp_obj of class Employeec using obj_salary, obj_age, obj_name set increase = call sal_increase of emp_obj set obj_salary = get_salary() of emp_obj display "Employee name: ", obj_name display "increase: ", increase, " new salary: ", obj_salary endfun main endclass Memployeec
On the CD | The Java implementation of class Employeec is shown next, and is stored in the file Employeec.java. |
// KJP v 1.1 File: Employeec.java, Sat Dec 21 14:47:01 2002 /** This class computes the salary increase for an employee. If his/her salary is greater than $45,000, the salary increase is 4.5%; otherwise, the salary increase is 5%. This is the class for employees. The main attributes are salary, age, and name. */ public class Employeec extends Person { private int years_service; private float salary; /** This is the initializer function (constructor), it initializes an object on creation. */ public Employeec(float isalary, int iage, String iname) // call the initializer in the base class {super(iage, iname); salary = isalary; years_service = 0; } // end constructor /** This function gets the salary of the employee object. */ public float get_salary() { return salary; } // end get_salary /** This accessor function gets the years of service of the employee object. */ public int get_years_serv() { return years_service; } // end get_years_serv /** This mutator function changes the years of service of the object by adding change_y to current years. This function is void. */ public void change_yearsv(int change_y) { years_service += change_y; } // end change_yearsv /** This function changes the salary of the Employee object by adding change to current salary. */ public void change_sal(float change) { salary += change; } // end change_sal /** This function computes the salary increase and updates the salary of an employee. It returns the increase. */ public float sal_increase() { // constant data declarations // percentages of salary increase final float percent1 = 0.045F; final float percent2 = 0.05F; float increase; // body of function starts here if ( salary > 45000) { increase = salary * percent1; } else { increase = salary * percent2; } // endif // update salary salary += increase; return increase; } // end sal_increase } // end Employeec
The resulting screen output from the execution of the program with class Memployeec is shown in Figure 12.3.
Figure 12.3: Output of execution of problem with class Memployeec.
When a subclass is a specialization of the base class, then one or more functions of the base class are redefined (or overridden) by the subclass. The subclass reimplements one or more functions of the base class.
Suppose that in the salary problem described in the previous section, a specialized class, Manager, includes a different calculation for salary increase. Objects of class Manager have similar characteristics as objects of class Employee. The only difference is that the salary increase is computed as 2.5% of the salary plus $2700.00.
On the CD | The KJP implementation of class Manager is stored in the file Manager.kpl and is shown next. |
Class Manager is a specialized version of class Employeec. Class Manager inherits class Employeec and overrides function sal_increase.
description This class computes the salary increase for a manager; the salary increase is 2.5% of the salary plus $2700.00. */ class Manager inherits Employeec is public description This is the initializer function (constructor), it initializes an object on creation. */ function initializer parameters real isalary, integer iage, string iname is begin // call the initializer of the base class call super using isalary, iage, iname endfun initializer description This function computes the salary increase and updates the salary of a manager object. It returns the increase. */ function sal_increase of type real is constants real MAN_PERCENT = 0.025 variables real increase real salary begin // body of function set salary = call get_salary set increase = salary * MAN_PERCENT + 2700.00 add increase to salary // update salary return increase endfun sal_increase endclass Manager
Class Manager does not include any attributes; the initializer function invokes the initializer of its base class to set the initial values of all the inherited attributes.
Attribute salary is a private attribute of the base class Employeec; to access the value of this attribute, function get_salary is called and is used to compute the salary increase in function sal_increase.
As mentioned before, a more practical case of inheritance involves the subclass as an extension and specialization of the base class.
On the CD | Class Mmanager includes the definition of function main, which creates and manipulates objects of class Manager. Class Mmanager is stored in file Mmanager.kpl. |