Inheritance (object-oriented programming)
Encyclopedia
In object-oriented programming
(OOP), inheritance is a way to reuse
code of existing objects, establish a subtype
from an existing object, or both, depending upon programming language support. In classical inheritance where objects are defined by classes
, classes can inherit attributes and behavior (i.e., previously coded algorithms associated with a class) from pre-existing classes called base classes or superclasses or parent classes or ancestor classes. The new classes are known as derived classes or subclasses or child classes. The relationships of classes through inheritance gives rise to a hierarchy
. In prototype-based programming
, objects can be defined directly from other objects without the need to define any classes, in which case this feature is called differential inheritance
.
Complex inheritance, or inheritance used within an insufficiently mature design, may lead to the yo-yo problem
.
The inheritance concept was invented in 1968 for Simula
.
from which other classes have been derived. The classes that are derived from a superclass are known as subclasses, or derived classes, or child classes.
A superclass allows for a generic interface to include specialized functionality through the use of virtual function
s.
The superclass mechanism is extensively used in object-oriented programming
because of the reusability
that can be achieved: common features are encapsulated in modular objects. Subclasses that wish to implement special behavior can do so via virtual methods, without having to reimplement the superclass's behavior.
A subclass is a class
that inherits
some properties from its superclass.
Subclasses and superclasses are often referred to as derived and base classes, respectively,
For instance, when programming animal behaviour, there may be the class of bird, of which all birds are derived. All birds may use the functionality of flying, but some may fly with a different techniques (swinging, using thermic winds like Albatroses). So, flying bird may use all the behaviour of birds, or call it and add some other behaviour for the bird species. And some that cannot fly anymore, like kiwi
, would override it with a method having no behaviour at all.
In most quarters, class inheritance for the sole purpose of code reuse has fallen out of favor. The primary concern is that implementation inheritance does not provide any assurance of polymorphic
substitutability—an instance of the reusing 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. Whereas public inheritance represents an "is-a
" relationship and delegation represents a "has-a
" relationship, private (and protected) inheritance can be thought of as an "is implemented in terms of" relationship.
Object Oriented-Software Construction, 2nd edition
by Bertrand Meyer
, the creator of the object-oriented programming language Eiffel
, lists twelve different uses of inheritance, most of which involve some amount of implementation inheritance.
Multiple inheritance
Hierarchical inheritance
Multilevel inheritance
Hybrid inheritance
enables a given type to be substituted for another type or abstraction. Subtyping is said to establish an is-a relationship between some existing abstraction, either implicitly or explicitly, depending on language support. The relationship can be expressed explicitly via inheritance in languages that support inheritance as a subtyping mechanism. For example, the following C++ code establishes an explicit inheritance relationship between classes B and A where B is a both a subclass and a subtype of A and can be used as an A wherever a reference (i.e., a reference or a pointer) to an A is specified.
In programming languages that do not support inheritance as a subtyping mechanism
, the relationship between a base class and a derived class is only a relationship between implementations (i.e., a mechanism for code reuse), as compared to a relationship between types
. Inheritance, even in programming languages that support inheritance as a subtyping mechanism, does not necessarily entail behavioral subtyping. It is entirely possible to derive a class whose object will behave incorrectly when used in a context where the parent class is expected; see the Liskov substitution principle
. (Compare connotation/denotation
.) In some, but not all OOP languages, the notions of code reuse and subtyping coincide because the only way to declare a subtype is to define a new class that inherits the implementation of another.
For example, consider a class
In defining this inheritance hierarchy we have already defined certain restrictions, not all of which are desirable:
The Composite reuse principle
is an alternative to inheritance. This technique supports polymorphism and code reuse by separating behaviors from the primary class hierarchy and including specific behavior classes as required in any business domain class. This approach avoids the static nature of a class hierarchy by allowing behavior modifications at run time and allows a single class to implement behaviors buffet-style, instead of being restricted to the behaviors of its ancestor classes.
One consequence of separation of roles and superclasses is that this cleanly separates compile-time and run-time aspects of the object system. Inheritance is then clearly a compile-time construct. it 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
Note that in this approach, all classes that are produced by this design process form 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 one assumes referential transparency, because roles are types of references and classes are types of the referred-to objects.
Object-oriented programming
Object-oriented programming is a programming paradigm using "objects" – data structures consisting of data fields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as data abstraction,...
(OOP), inheritance is a way to reuse
Reusability
In computer science and software engineering, reusability is the likelihood a segment of source code that can be used again to add new functionalities with slight or no modification...
code of existing objects, establish a subtype
Subtype polymorphism
In programming language theory, subtyping or subtype polymorphism is a form of type polymorphism in which a subtype is a datatype that is related to another datatype by some notion of substitutability, meaning that program constructs, typically subroutines or functions, written to operate on...
from an existing object, or both, depending upon programming language support. In classical inheritance where objects are defined by classes
Class (computer science)
In object-oriented programming, a class is a construct that is used as a blueprint to create instances of itself – referred to as class instances, class objects, instance objects or simply objects. A class defines constituent members which enable these class instances to have state and behavior...
, classes can inherit attributes and behavior (i.e., previously coded algorithms associated with a class) from pre-existing classes called base classes or superclasses or parent classes or ancestor classes. The new classes are known as derived classes or subclasses or child classes. The relationships of classes through inheritance gives rise to a hierarchy
Hierarchy
A hierarchy is an arrangement of items in which the items are represented as being "above," "below," or "at the same level as" one another...
. In prototype-based programming
Prototype-based programming
Prototype-based programming is a style of object-oriented programming in which classes are not present, and behavior reuse is performed via a process of cloning existing objects that serve as prototypes. This model can also be known as classless, prototype-oriented or instance-based programming...
, objects can be defined directly from other objects without the need to define any classes, in which case this feature is called differential inheritance
Differential inheritance
Differential Inheritance is a common inheritance model used by prototype-based programming languages such as JavaScript, Io and NewtonScript. It operates on the principle that most objects are derived from other, more general objects, and only differ in a few small aspects; while usually...
.
Complex inheritance, or inheritance used within an insufficiently mature design, may lead to the yo-yo problem
Yo-yo problem
In computer science, the yo-yo problem is an anti-pattern that occurs when a programmer has to read and understand a program whose inheritance graph is so long and complicated that the programmer has to keep flipping between many different class definitions in order to follow the control flow of...
.
The inheritance concept was invented in 1968 for Simula
Simula
Simula is a name for two programming languages, Simula I and Simula 67, developed in the 1960s at the Norwegian Computing Center in Oslo, by Ole-Johan Dahl and Kristen Nygaard...
.
Subclasses and superclasses
A superclass, base class, or parent class is a classClass (computer science)
In object-oriented programming, a class is a construct that is used as a blueprint to create instances of itself – referred to as class instances, class objects, instance objects or simply objects. A class defines constituent members which enable these class instances to have state and behavior...
from which other classes have been derived. The classes that are derived from a superclass are known as subclasses, or derived classes, or child classes.
A superclass allows for a generic interface to include specialized functionality through the use of virtual function
Virtual function
In object-oriented programming, a virtual function or virtual method is a function or method whose behaviour can be overridden within an inheriting class by a function with the same signature...
s.
The superclass mechanism is extensively used in object-oriented programming
Object-oriented programming
Object-oriented programming is a programming paradigm using "objects" – data structures consisting of data fields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as data abstraction,...
because of the reusability
Reusability
In computer science and software engineering, reusability is the likelihood a segment of source code that can be used again to add new functionalities with slight or no modification...
that can be achieved: common features are encapsulated in modular objects. Subclasses that wish to implement special behavior can do so via virtual methods, without having to reimplement the superclass's behavior.
A subclass is a class
Class (computer science)
In object-oriented programming, a class is a construct that is used as a blueprint to create instances of itself – referred to as class instances, class objects, instance objects or simply objects. A class defines constituent members which enable these class instances to have state and behavior...
that inherits
Inheritance (computer science)
In object-oriented programming , inheritance is a way to reuse code of existing objects, establish a subtype from an existing object, or both, depending upon programming language support...
some properties from its superclass.
Subclasses and superclasses are often referred to as derived and base classes, respectively,
Applications
Inheritance is used to co-relate two or more classes to each other. With the use of inheritance we can use the methods and the instance variables of other classes in any other classes.Overriding
Many object-oriented programming languages permit a class or object to replace the implementation of an aspect—typically a behavior—that it has inherited. This process is usually called overriding. Overriding introduces a complication: which version of the behavior does an instance of the inherited class use—the one that is part of its own class, or the one from the parent (base) class? The answer varies between programming languages, and some languages provide the ability to indicate that a particular behavior is not to be overridden and behave according to the base class. For instance, in C#, the overriding of a method should be specified by the program. An alternative to overriding is hiding the inherited code.Code reuse
One of the earliest motivations for using inheritance was the reuse of code that already existed in another class. This practice is usually called implementation inheritance. Before the object-oriented paradigm was in use, one had to write similar functionality over and over again. With inheritance, behaviour of a superclass can be inherited by subclasses. It not only possible to call the overridden behaviour (method) of the ancestor (superclass) before adding other functionalities, one can override the behaviour of the ancestor completely.For instance, when programming animal behaviour, there may be the class of bird, of which all birds are derived. All birds may use the functionality of flying, but some may fly with a different techniques (swinging, using thermic winds like Albatroses). So, flying bird may use all the behaviour of birds, or call it and add some other behaviour for the bird species. And some that cannot fly anymore, like kiwi
Kiwi
Kiwi are flightless birds endemic to New Zealand, in the genus Apteryx and family Apterygidae.At around the size of a domestic chicken, kiwi are by far the smallest living ratites and lay the largest egg in relation to their body size of any species of bird in the world...
, would override it with a method having no behaviour at all.
In most quarters, class inheritance for the sole purpose of code reuse has fallen out of favor. The primary concern is that implementation inheritance does not provide any assurance of polymorphic
Polymorphism in object-oriented programming
Subtype polymorphism, almost universally called just polymorphism in the context of object-oriented programming, is the ability to create a variable, a function, or an object that has more than one form. The word derives from the Greek "πολυμορφισμός" meaning "having multiple forms"...
substitutability—an instance of the reusing class cannot necessarily be substituted for an instance of the inherited class. An alternative technique, delegation
Delegation pattern
In software engineering, the delegation pattern is a design pattern in object-oriented programming where an object, instead of performing one of its stated tasks, delegates that task to an associated helper object. There is an Inversion of Responsibility in which a helper object, known as a...
, requires more programming effort, but avoids the substitutability issue. In C++
C++
C++ is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features. It was developed by Bjarne Stroustrup starting in 1979 at Bell...
private inheritance can be used as form of implementation inheritance without substitutability. Whereas public inheritance represents an "is-a
Is-a
In knowledge representation, object-oriented programming and design, is-a or is_a or is a is a relationship where one class D is a subclass of another class B ....
" relationship and delegation represents a "has-a
Has-a
In database design and object oriented program architecture, has-a is a relationship where one object "belongs" to another object , and behaves according to the rules of ownership. In simple words, has-a relationship in an object is called a member field of an object...
" relationship, private (and protected) inheritance can be thought of as an "is implemented in terms of" relationship.
Object Oriented-Software Construction, 2nd edition
Object-Oriented Software Construction
Object-Oriented Software Construction is a book by Bertrand Meyer, widely considered a foundational text of object-oriented programming. The first edition was published in 1988; the second, extensively revised and expanded edition , in 1997...
by Bertrand Meyer
Bertrand Meyer
Bertrand Meyer is an academic, author, and consultant in the field of computer languages. He created the Eiffel programming language.-Education and academic career:...
, the creator of the object-oriented programming language Eiffel
Eiffel (programming language)
Eiffel is an ISO-standardized, object-oriented programming language designed by Bertrand Meyer and Eiffel Software. The design of the language is closely connected with the Eiffel programming method...
, lists twelve different uses of inheritance, most of which involve some amount of implementation inheritance.
Forms of inheritance
Single inheritance- When a subclass inherits only from one base class
Multiple inheritance
Multiple inheritance
Multiple inheritance is a feature of some object-oriented computer programming languages in which a class can inherit behaviors and features from more than one superclass....
- When a subclass inherits from multiple base classes.
Hierarchical inheritance
- When many subclasses inherit from a single base class
Multilevel inheritance
- When a subclass inherits from a class that itself inherits from another class. The transitive nature of inheritance is reflected by this form of inheritance.
Hybrid inheritance
- A combination of two or more forms of inheritance; for example, when a subclass inherits from multiple base classes and all of its base classes inherit from a single base class
Inheritance vs subtyping
SubtypingSubtype polymorphism
In programming language theory, subtyping or subtype polymorphism is a form of type polymorphism in which a subtype is a datatype that is related to another datatype by some notion of substitutability, meaning that program constructs, typically subroutines or functions, written to operate on...
enables a given type to be substituted for another type or abstraction. Subtyping is said to establish an is-a relationship between some existing abstraction, either implicitly or explicitly, depending on language support. The relationship can be expressed explicitly via inheritance in languages that support inheritance as a subtyping mechanism. For example, the following C++ code establishes an explicit inheritance relationship between classes B and A where B is a both a subclass and a subtype of A and can be used as an A wherever a reference (i.e., a reference or a pointer) to an A is specified.
In programming languages that do not support inheritance as a subtyping mechanism
Subtype polymorphism
In programming language theory, subtyping or subtype polymorphism is a form of type polymorphism in which a subtype is a datatype that is related to another datatype by some notion of substitutability, meaning that program constructs, typically subroutines or functions, written to operate on...
, the relationship between a base class and a derived class is only a relationship between implementations (i.e., a mechanism for code reuse), as compared to a relationship between types
Data type
In computer programming, a data type is a classification identifying one of various types of data, such as floating-point, integer, or Boolean, that determines the possible values for that type; the operations that can be done on values of that type; the meaning of the data; and the way values of...
. Inheritance, even in programming languages that support inheritance as a subtyping mechanism, does not necessarily entail behavioral subtyping. It is entirely possible to derive a class whose object will behave incorrectly when used in a context where the parent class is expected; see the Liskov substitution principle
Liskov substitution principle
Substitutability is a principle in object-oriented programming. It states that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S without altering any of the desirable properties of that program...
. (Compare connotation/denotation
Connotation (semiotics)
In semiotics, connotation arises when the denotative relationship between a signifier and its signified is inadequate to serve the needs of the community. A second level of meanings is termed connotative...
.) In some, but not all OOP languages, the notions of code reuse and subtyping coincide because the only way to declare a subtype is to define a new class that inherits the implementation of another.
Limitations and alternatives
When using inheritance extensively in designing a program, one should note certain constraints that it imposes.For example, consider a class
Person
that contains a person's name, address, phone number, age, gender, 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:
Design constraints
- Singleness: using single inheritance, a subclass can inherit from only one superclass. Continuing the example given above,
Person
can be either aStudent
or anEmployee
, but not both. Using multiple inheritanceMultiple inheritanceMultiple inheritance is a feature of some object-oriented computer programming languages in which a class can inherit behaviors and features from more than one superclass....
partially solves this problem, as one can then define aStudentEmployee
class that inherits from bothStudent
andEmployee
. 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.
- Static: the inheritance hierarchy of an object is fixed at instantiationInstance (computer science)In object-oriented programming an instance is an occurrence or a copy of an object, whether currently executing or not. Instances of a class share the same set of attributes, yet will typically differ in what those attributes contain....
when the object's type is selected and does not change with time. For example, the inheritance graph does not allow aStudent
object to become aEmployee
object while retaining the state of itsPerson
superclass. (Although similar behavior can be achieved with the decorator patternDecorator patternIn object-oriented programming, the decorator pattern is a design pattern that allows behaviour to be added to an existing object dynamically.-Introduction:...
.) Some have criticized inheritance, contending that it locks developers into their original design standards.
- Visibility: whenever client code has access to an object, it generally has access to all the object's superclass data. Even if the superclass has not been declared public, the client can still cast the object to its superclass type. For example, there is no way to give a function a pointer to a
Student
's grade point average and transcript without also giving that function access to all of the personal data stored in the student'sPerson
superclass. Many modern languages, including C++ and Java, provide a "protected" access modifier that allows subclasses to access the data, without allowing any code outside the chain of inheritance to access it. This largely mitigates this issue.
The Composite reuse principle
Composite reuse principle
Composition over inheritance in object-oriented programming is a technique by which classes may achieve polymorphic behavior and code reuse by containing other classes which implement the desired functionality instead of through inheritance....
is an alternative to inheritance. This technique supports polymorphism and code reuse by separating behaviors from the primary class hierarchy and including specific behavior classes as required in any business domain class. This approach avoids the static nature of a class hierarchy by allowing behavior modifications at run time and allows a single class to implement behaviors buffet-style, instead of being restricted to the behaviors of its ancestor classes.
Roles and inheritance
Sometimes inheritance-based design is used instead of roles. A role, say Student role of a Person describes a characteristic associated to the object that is present because the object happens to participate in some relationship with another object (say the person in student role -has enrolled- to the classes). Some object-oriented design methods do not distinguish this use of roles from more stable aspects of objects. Thus there is a tendency to use inheritance to model roles, say you would have a Student role of a Person modelled as a subclass of a Person. However, neither the inheritance hierarchy nor the types of the objects can change with time. Therefore, modelling roles as subclasses can cause the roles to be fixed on creation, say a Person cannot then easily change his role from Student to Employee when the circumstances change. From modelling point of view, such restrictions are often not desirable, because this causes artificial restrictions on future extensibility of the object system, which will make future changes harder to implement, because existing design needs to be updated. Inheritance is often better used with a generalization mindset, such that common aspects of instantiable classes are factored to superclasses; say having a common superclass 'LegalEntity' for both Person and Company classes for all the common aspects of both. The distinction between role based design and inheritance based design can be made based on the stability of the aspect. Role based design should be used when it's conceivable that the same object participates in different roles at different times, and inheritance based design should be used when the common aspects of multiple classes (not objects!) are factored as superclasses, and do not change with time.One consequence of separation of roles and superclasses is that this cleanly separates compile-time and run-time aspects of the object system. Inheritance is then clearly a compile-time construct. it 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 form 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 one assumes referential transparency, because roles are types of references and classes are types of the referred-to objects.
See also
- Circle-ellipse problemCircle-ellipse problemThe circle-ellipse problem in software development illustrates a number of pitfalls which can arise when using subtype polymorphism in object modelling...
- Class (object-oriented programming)
- Composition in object-oriented programming
- Defeasible reasoningDefeasible reasoningDefeasible reasoning is a kind of reasoning that is based on reasons that are defeasible, as opposed to the indefeasible reasons of deductive logic...
- Differential inheritanceDifferential inheritanceDifferential Inheritance is a common inheritance model used by prototype-based programming languages such as JavaScript, Io and NewtonScript. It operates on the principle that most objects are derived from other, more general objects, and only differ in a few small aspects; while usually...
- Interface (computer science)Interface (computer science)In the field of computer science, an interface is a tool and concept that refers to a point of interaction between components, and is applicable at the level of both hardware and software...
- Interface inheritance
- Multiple inheritanceMultiple inheritanceMultiple inheritance is a feature of some object-oriented computer programming languages in which a class can inherit behaviors and features from more than one superclass....
- Override (object-oriented programming)
- Polymorphism in object-oriented programmingPolymorphism in object-oriented programmingSubtype polymorphism, almost universally called just polymorphism in the context of object-oriented programming, is the ability to create a variable, a function, or an object that has more than one form. The word derives from the Greek "πολυμορφισμός" meaning "having multiple forms"...
- Role-Oriented ProgrammingRole-Oriented ProgrammingRole-oriented programming is a form of computer programming aimed at expressing things in terms which are analogous to human conceptual understanding of the world. This should make programs easier to understand and maintain....
- The Third ManifestoThe Third ManifestoThe Third Manifesto is Christopher J. Date's and Hugh Darwen's proposal for future database management systems, a response to two earlier Manifestos with the same purpose. The theme of the manifestos is how to avoid the 'object-relational impedance mismatch' between object-oriented programming...
- Virtual inheritanceVirtual inheritanceVirtual inheritance is a topic of object-oriented programming. It is a kind of inheritance in which the part of the object that belongs to the virtual base class becomes common direct base for the derived class and any next class that derives from it...