In object-oriented programming, inheritance is a way to form new classes (instances of which are called objects) using classes that have already been defined. The former, known as derived classes, take over (or inherit) attributes and behaviour of the latter, which are referred to as base classes. It is intended to help reuse of existing code with little or no modification.
Moreover, inheritance is also called generalization, because the is-a relationships capture a hierarchical relationship between classes of objects. For instance, a "fruit" is a generalization of "apple", "orange", "mango" and many others. We say that fruit is an abstraction of apple, orange, etc. Conversely, we can say that since apples are fruit (i.e. an apple is-a fruit), that they inherit all the properties common to all fruit, such as being a fleshy container for the seed of a plant.
Therefore, one of the powerful advantages of inheritance is that modules with sufficiently similar interfaces can be commanded by shared controlling code, reducing the complexity of the program. Inheritance therefore has another view, a dual, called polymorphism, which describes many pieces of code being controlled by shared control code.
Complex inheritances may cause the Yo-yo problem.
Another form of specialization occurs when an inherited class specifies that it has a particular behavior but does not actually implement the behavior. Each non-abstract, concrete class which inherits from that abstract class must provide an implementation of that behavior. This providing of actual behavior by a subclass is sometimes known as implementation or reification.
Extension is often used when incorporating the new features into the inherited class is either not possible or not appropriate. It can also be used at the object level, such as in the Decorator pattern.
In most quarters, class inheritance for the sole purpose of code re-use has fallen out of favor. The primary concern is that implementation inheritance does not provide any assurance of polymorphic substitutability—an instance of the re-using class cannot necessarily be substituted for an instance of the inherited class. An alternative technique, delegation, requires more programming effort but avoids the substitutability issue. In C++ private inheritance can be used as form of implementation inheritance without substitutability.
The notion that implementation inheritance should be avoided is not universal. One prominent object-oriented programming expert who believes that implementation inheritance has its place is Bertrand Meyer. In his book Object Oriented Software Construction, 2nd ed., Meyer lists twelve different uses of inheritance that he considers to be legitimate, most of which involve some amount of implementation inheritance.
Animal that contained such data that denoted whether the animal was presently alive, where it was currently located, etc.; as well as methods instructing the animal to eat, move, mate, etc. If we wanted to create a class Mammal, most of those data elements and functions would be the same as for most animals, but a few would change. We therefore define Mammal as a subclass of Animal (we then say that Animal is Mammal's superclass or parent class):
Note here that we don't need to specify that a mammal has all the usual animal things: a location, ability to eat, move, etc. We do add some additional features such as hair and breasts that are unique to mammals, and we redefine the reproduce method to add functionality. Within the reproduce method, note the call super.reproduce(). This is a call to the superclass method which we are redefining. This roughly means "do whatever a member of my superclass would do", which is then followed by code specific to our new subclass.
class Mammal extends Animal
{
Hair m_h;
Breasts m_b;
Mammal reproduce()
{
Mammal offspring;
super.reproduce();
if (is_female())
{
offspring = super.give_birth();
offspring.breastfeed(m_b);
}
care_for_young(offspring);
return offspring;
}
}
For example, consider a class Person that contains a person's name, address, phone number, age, sex, and race. We can define a subclass of Person called Student that contains the person's grade point average and classes taken, and another subclass of Person called Employee that contains the person's job title, employer, and salary.
In defining this inheritance hierarchy we have already defined certain restrictions, not all of which are desirable:
Person can be either a Student or an Employee, but not both. Using multiple inheritance partially solves this problem, as a StudentEmployee class can be defined that inherits from both Student and Employee. However, it can still inherit from each superclass only once; this scheme does not support cases in which a student has two jobs or attends two institutions.
Student object to become a Employee object while retaining the state of its Person superclass.
Student's grade point average and transcript without also giving that function access to all of the personal data stored in the student's Person superclass.
One consequence of separation of roles and superclasses is that compile-time and run-time aspects of the object system are cleanly separated. Inheritance is then clearly a compile-time construct. Inheritance does influence the structure of many objects at run-time, but the different kinds of structure that can be used are already fixed at compile-time.
To model the example of Person as an employee with this method, the modelling ensures that a Person class can only contain operations or data that are common to every Person instance regardless of where they are used. This would prevent use of a Job member in a Person class, because every person does not have a job, or at least it is not known that the Person class is only used to model Person instances that have a job. Instead, object-oriented design would consider some subset of all person objects to be in an "employee" role. The job information would be associated only to objects that have the employee role. Object-oriented design would also model the "job" as a role, since a job can be restricted in time, and therefore is not a stable basis for modelling a class. The corresponding stable concept is either "WorkPlace" or just "Work" depending on which concept is meant. Thus, from object-oriented design point of view, there would be a "Person" class and a "WorkPlace" class, which are related by a many-to-many associatation "works-in", such that an instance of a Person is in employee role, when he works-in a job, where a job is a role of his work place in the situation when the employee works in it.
Note that in this approach, all classes that are produced by this design process are part of the same domain, that is, they describe things clearly using just one terminology. This is often not true for other approaches.
The difference between roles and classes is especially difficult to understand if referential transparency is assumed, because roles are types of references and classes are types of the referred-to objects.
Transcript and Job to store the additional information for a student and employee, respectively. Then, each Person object can contain a collection of Transcript objects and a collection of Job objects. This removes the aforementioned constraints:
Person can now have an arbitrary number of jobs and attend an arbitrary number of institutions
Transcript to a function--for example, one that makes college admissions decisions--without also automatically passing in the student's name, age, race, and other personal information.
Using composition instead of inheritance also leads to less ambiguous syntax. For example, in an inheritance-oriented design, one might encounter the following code:
Employee e = getEmployee();
print(e.jobTitle());
While one might infer that the jobTitle() function is defined in the Employee class, it is also possible that it is defined in the Person class. As the inheritance hierarchy gets deeper, this effect, known as the yo-yo problem, is magnified.
A composition-based design allows the programmer to maintain a shallower inheritance hierarchy, and minimizes ambiguity, as in the following example:
Person p = getPerson();
print(p.job().title());
To a programmer that knows the Job class has no superclass, it is immediately obvious that the title() function is defined in the Job class.
Component-oriented design cannot be substituted for an inheritance-based design in all cases. For example, inheritance enables polymorphism and encapsulation. Also, defining component classes instead of subclasses can increase the length of source code.
Vererbung (Programmierung) | Héritage (Informatique) | Ereditarietà (informatica) | Paveldėjimas (programavimas) | Overerving (informatica) | 継承 | Dziedziczenie (programowanie obiektowe) | Herança | Наследование (программирование) | Perintä (ohjelmointi) | மரபியல்பு (கணினியியல்) | 继承 (计算机科学)
This article is licensed under the GNU Free Documentation License.
It uses material from the
"Inheritance (computer science)".
Home Page • arts • business • computers • games • health • hospitals • home • kids & teens • news • physicians • recreation• reference • regional • science • shopping • society • sports • world