Inheritance (programming)
The Inheritance ( English inheritance ) is one of the basic concepts of object orientation and has great significance in the software development . Inheritance is used to create new classes based on existing classes , the relationship between the original and the new class being permanent. A new class can be an extension or a restriction of the original class. In addition to this constructive aspect, inheritance also serves to document similarities between classes, which is particularly important in the early phases of software design . Class hierarchies based on inheritance reflect structural and behavioral similarities of the classes.
The inheriting class is mostly base class (also Super - upper or - parent class ) called the inheriting derived class (also sub -, sub - or child class ). The process of inheritance is usually called derivation or specialization , the reverse of this is called generalization , which is a term that is mainly limited to the model level . In the Unified Modeling Language (UML), an inheritance relationship is represented by an arrow with a triangular tip pointing from the derived class to the base class. Inherited attributes and methods are not repeated in the representation of the derived class.
In the Simula programming language , inheritance was first introduced in 1967 with further concepts of object-oriented programming . The latter has since opened up important new perspectives in software development and also made component-based development possible.
Derived class and base class typically have an "is-a" relationship to one another. Classes are used to specify the data type and functionality, both of which can be inherited. Some programming languages separate at least partially between these aspects and distinguish between interface (English. Interface ) and class. When a derived class inherits from more than one base class, this is called multiple inheritance . Multiple inheritance is not possible with all programming languages, with some only in a restricted form.
example
The following example shows a possible excerpt from the application area of vehicle rental support . The base class Fahrzeug
contains the attributes Fahrzeugnummer
, Leergewicht
and ZulässigesGesamtgewicht
. The specializations Kraftfahrzeug
and Fahrrad
add further attributes to the weight information inherited from the base class and the identifying vehicle number. In any object of the class Kraftfahrzeug
so the attributes Fahrzeugnummer
, Leergewicht
, ZulässigesGesamtgewicht
, Höchstgeschwindigkeit
and Leistung
stored. In the class Fahrzeug
there is the method PruefeVerfuegbarkeit
that uses the to determine Fahrzeugnummer
the availability of a specific vehicle, for example through a database access . This method is inherited by all specializations and can therefore also be used for them. The same applies if another method is added to the class at a later date Fahrzeug
, for example a method HatNavigationssystem
if some of the vehicles are equipped with navigation systems.
Kraftfahrzeug
The method is PrüfeFahrerlaubnis
introduced in the class . When a specific driving license is handed over, this method is intended to determine whether the vehicle represented by an object of this class may be driven with this driving license. The driving license could be country-specific, and the countries in which the motor vehicle is to be operated must also be taken into account. Based on the attributes Höchstgeschwindigkeit
and Leistung
possibly already in the class Kraftfahrzeug
, some implementations are made if the suitability of the driving license for all vehicles operated a country already on the basis of the gross vehicle weight is decidable maximum speed and performance. Many cases are but only at the level of specialization Motorrad
, PKW
and LKW
so this method in these classes decidable overwritten must be. For example, the number of seats in the motor vehicle must be taken into account in some cases.
Within an application program that implements this model, the specific vehicle to be rented, that is to say the corresponding specialization, would be instantiated in order to check whether a driving license is valid after entering the corresponding vehicle data.
In addition, an object would also be generated for the present driving license. This would be transferred to the method of PrüfeFahrerlaubnis
the vehicle object and evaluated by it. The result of the check could, for example, be displayed to the clerk. The structure of the memory image is shown schematically in the figure opposite for an object of the class PKW
. The attributes inherited from the various classes are typically in direct succession. Furthermore, the memory image of an object contains a pointer to the so-called table of virtual methods , which is used to determine the entry point of the specific implementation when a method is called.
Applications of Inheritance
In software development, inheritance enables modeling that comes very close to the human imagination of the real world. There are very different uses for the inheritance mechanism. As before, it is debatable whether the inheritance should be used only for very narrowly defined areas of application and if a deployment with the main intention of reusing code of software quality is more detrimental.
The following application contexts are recommended or appear in practice:
- Subtype inheritance: With this type of inheritance, the inheriting class is a subtype of the base class in the sense of an abstract data type . This means that an object of the subtype can be used at any point where an object of the basic type is expected. The set of possible expressions of the subtype represents a subset of those of the basic type.
- Inheritance for expansion: In the derived class, new functionality is added compared to the base class. This variant of inheritance appears to be in contradiction to the restrictive subtype inheritance. However, the extension refers to additional attributes. This variant also includes adjustments by overwriting methods, for example to add functionality that is not relevant in the base class. This variant also includes the case that only part of the functionality of an abstract class is implemented in the derived - in this case also abstract - class, and additionally required implementations are reserved for further specializations (reification) .
- Inheritance to support general skills: This variant is about establishing the support of the basic functionality of an application architecture or class library . A basic functionality such as serializability or comparability is declared by an abstract class ( interface ) - typical identifiers are Serializable and Comparable . The implementation of all requirements of the interface must be done in the derived class. Formally, this type of inheritance corresponds to subtype inheritance.
- Inheritance of standard implementations: General functionality that can be used for several types is implemented in central classes. This variant is used for the appropriate reuse of general program parts ( mixin class ).
There are also uses of inheritance that are not considered useful. In particular, the first steps in object-oriented programming often result in an exaggerated gradation of the inheritance hierarchy resulting from enthusiasm, often for a simple additional property. For example, for a class Person
the specializations WeiblichePerson
and should be MännlichePerson
useful in very few cases and rather hinder the modeling of the actually relevant aspects. Another questionable use is when the inheriting class is not in an “is-a” but in a “has” relationship to the base class, and an aggregation would be appropriate. Often this occurs in connection with multiple inheritance. Apfelkuchen
as an inheritor of Kuchen
and Apfel
is a pictorial example of this modeling error, as there is Apfel
no meaningful base class.
During the transition from object-oriented modeling to programming, there is the situation that the modeling of a classifying hierarchy of the technical application objects cannot easily be transferred to the program level. For example, from a conceptual point of view, the modeling of Kunde
and Mitarbeiter
as specializations of may Person
appear useful. At the programming level, such a classification is on the one hand static - that is, a person cannot easily change from the role of the employee to the role of the customer in terms of programming. On the other hand, a person cannot take on several roles at the same time in this way. The fact that the latter cannot be sensibly KundeUndMitarbeiter
resolved by adding a further specialization that inherits multiple times becomes Lieferant
clear , for example, when adding another role . The usual solution is to separate the aspects and model an associative relationship between Person
and their roles.
Variants of inheritance of type and implementation
By means of inheritance, both the type, which is specified by its interface, and the functionality can be passed on to the derived class. The consequences of this double function of inheritance have been discussed controversially for years. More recent programming languages such as Java or .NET languages such as C # and VB.NET do not support continuous separation of these variants inheritance, but provide for interfaces (interface) and Classes (class) two formally separate concepts. Three cases can be distinguished:
- Inheritance of type and implementation (usually implementation inheritance or just called inheritance , English subclassing )
- Type inheritance (usually referred to as interface inheritance , English subtyping )
- Pure inheritance of the implementation (not directly possible in Java or .NET languages)
In the last variant, the derived class and the base class are not in an “is-a” relationship.
Implementation inheritance
The implementation and, implicitly, its interface are inherited from the base class. The derived class adopts the attributes and functionality of the base class and, if necessary, changes them or supplements them with additional properties that are relevant for this specialization. The derived class also benefits if the functionality of the base class is added or improved at a later date.
In the following, an example of the derivation of Quadrat
as a specialization of is Rechteck
outlined in the Java programming language . This example can often be found in a similar form in the literature and is helpful to illustrate many - even unfavorable - aspects, but it cannot really be considered a particularly good example of inheritance.
The class Rechteck
has the attributes laenge
and breite
, which are set via the constructor . There are also methods ( functions ) for calculating the circumference and length of the diagonals of the rectangle. The specialization Quadrat
inherits this functionality ( keyword extends
). The constructor for Quadrat
now only requires one parameter instead of two , since length and width are the same. The Rechteck
calculations of circumference and diagonal length implemented in the class are also correct for the square. In this example, for the sake of illustration - for reasons of optimization - a modification of the calculation of the diagonal length is carried out, since this can be calculated in a simpler way with a square. The calculation of the scope is not reimplemented, but taken over from the base class - although a slight simplification would of course also be possible there.
public class Rechteck
{
private double laenge;
private double breite;
public Rechteck(double laenge, double breite)
{
this.breite = breite;
this.laenge = laenge;
}
public double getLaenge() { return laenge; }
public double getBreite() { return breite; }
public double getUmfang()
{
return 2 * laenge + 2 * breite;
}
public double getDiagonale()
{
return Math.sqrt(laenge * laenge + breite * breite);
}
}
public class Quadrat extends Rechteck
{
// Einmalige Berechnung der Wurzel aus 2
private static final double WURZEL2 = Math.sqrt(2);
public Quadrat(int laenge)
{
// Aufruf des Konstruktors der Basisklasse
super(laenge, laenge);
}
@Override
public double getDiagonale()
{
return WURZEL2 * getLaenge();
}
}
Interface inheritance
There have been two parallel developments in software development since the 1970s, one of which resulted in object-oriented programming , and on the other hand, algebraic specification methods were developed to support software design. One advantage of such specifications is that they can be provided with mathematical semantics . A key result of these efforts was the concept of the abstract data type , which aims to specify a data type regardless of its implementation. Classes , more precisely their interfaces , are regarded as the image of an abstract data type. In this case, however, it is actually inappropriate that in the case of inheritance, practically no language explicitly supports a consistent separation of the inheritance of interface and implementation. Although relatively new languages such as Java and .NET languages lead to the interfaces (interfaces) , a concept for illustration of abstract data types, but do not support continuous separation, as is an interface once implemented by a class, inherits any further specialization both the implementation as also the interface. Specialists in object-oriented programming, such as Bertrand Meyer , see more harm than good in a complete split. One reason is that the proximity of the interface and implementation in the program code makes it easier to understand and maintain .
In this context, the Liskovian substitution principle is also important . This requires that a subtype must behave in such a way that someone who thinks they are looking at an object of the base type is not surprised by unexpected behavior when it is actually an object of the subtype. Object-oriented programming languages can not rule out a violation of this principle, which can occur due to the polymorphism associated with inheritance , from the outset. A violation of the principle is often not obvious at first glance. If, for example, in the example outlined above, Rechteck
the methods setLaenge
and are setBreite
introduced in the base class to subsequently change the size , then the class must Quadrat
decide how to handle them. One possible solution is that when the length is set, the width is automatically set to the same value and vice versa. If an application assumes that it has a rectangle in front of it and expects the area to double when the length of a rectangle is doubled, the Quadrat
quadrupling of the area caused by automatic equalization of the width is surprising for an instance of the type .
In practice, the lack of separation between type and implementation inheritance often means that implementation details shine through in the interface of a class. One strategy to avoid this effect is to use abstract classes or interfaces in the root areas of the class hierarchy. It is beneficial to differentiate as far as possible on the abstract level before implementations are added. Such an interface-based basis is also necessary in connection with distributed architectures such as CORBA or COM .
Pure implementation inheritance
In the case of pure implementation inheritance , which is also referred to as private inheritance , the inheriting class uses the functionality and attributes of the base class without being considered a subclass of this class. As a - somewhat constructed - example, a class RechtwinkligesDreieck
from the class of Rechteck
the above example could inherit the implementation to calculate the hypotenuse via the method getDiagonale
after inserting the length of the legs for length and width.
For example, in C ++ or Eiffel there is the possibility of pure implementation inheritance, in Java or the .NET languages there is no. An alternative for the latter languages is to use delegation , which requires a lot more program code.
Interaction of the methods in the class hierarchy
If a method is overwritten in a class , often only functionality should be added and the implementation of the base class should continue to be used, since this already covers general aspects that are also valid for the specialization. For this it is necessary that the equivalent of the base class is called within the method implementation of the specialized class. This call is typically made at the beginning or at the end of the overwriting method, but in some cases additional functionality must be implemented before and after this call.
The different programming languages allow the base class implementation to be called in different ways. C ++ offers the greatest degree of freedom, where the method name is prefixed with the class name (scope operator) . This procedure goes far beyond this application, because it enables any method of all classes within the class hierarchy to be called. Java, for example, is somewhat more restrictive; there is the keyword super
that precedes the method name. Calling the base class method is much more formal, for example in the CLOS language : There call-next-method
the base implementation is called using the keyword alone , without specifying the method name or parameters ; the current parameters of the specializing method are passed implicitly. The more formal approach is less redundant and error-prone, but offers less flexibility.
Such a call cascade can be explained using the introductory example. The method PruefeFahrerlaubnis
returns whether the test could be carried out and, if this is the case, also the result of this test. The implementation of the class PKW
first calls the implementation of the class Kraftfahrzeug
in order to deal with the cases that can be decided on the basis of maximum speed, power or permissible total weight. The implementation in Kraftfahrzeug
turn delegates the checking of the permissible total weight to its base class. After returning from the called basic implementations, the check is continued if the case has not yet been decided.
Special features of inheritance
Multiple inheritance
Multiple inheritance is when a derived class inherits directly from more than one base class. A sequential, multi-level inheritance, however, is not referred to as multiple inheritance. A very common application of multiple inheritance is the use of mixin classes , which contribute generally usable implementations and thus serve to avoid redundancy .
Another example of multiple inheritance results from expanding the introductory example to include the classes Schienenfahrzeug
and Zweiwegefahrzeug
. The latter inherits both from Kraftfahrzeug
and from Schienenfahrzeug
and thus has all the attributes of the motor vehicles as well as the additional attribute Spurweite
that is Schienenfahrzeug
inherited from.
The need for multiple inheritance is controversial, it is not supported by all languages, such as Smalltalk . The first language to support multiple inheritance was Flavors , an object-oriented extension of Lisp . C ++ , Eiffel and Python , for example, also offer comprehensive support . Java and .NET languages offer limited support; there a class can inherit from any number of interfaces , but only from a class that contains implementations. Another solution keeps Ruby ready, there only a direct base class is also possible, but a class can many so-called arbitrary Modules include what the basic idea of a mixin equivalent of inheritance right.
In addition to considerable additional implementation effort for the compiler and runtime environment, there are two main reasons for the frequent lack of or limited support:
- Possible name collisions with inherited attributes or methods
- Multiple occurrences of the same base class in the inheritance tree
For the first problem, the languages usually offer options for renaming. The latter constellation, also known as the Diamond problem , only occurs when the implementation is inherited. It can make sense here that the resulting object contains only one instance of the class that occurs repeatedly, as well as several. For the above example of the two-way vehicle this means either the presence of only one instance of the base class Fahrzeug
or of two. C ++ offers both options through the concept of so-called virtual base classes . Eiffel also offers both options and this even at the level of individual attributes and methods. In the example outlined, this can even make sense: The unladen weight of a road-rail vehicle is basically the same, regardless of whether it is operated by rail or road. However, this does not necessarily have to apply to the gross vehicle weight. Python has implemented the concept of so-called C3 linearization in such cases to create a meaningful inheritance hierarchy from version 2.3 .
Multilevel inheritance
In object-oriented programming, there is often the problem that different classes have been defined that can not access variables from one another. Inheritance can be used to make the attributes and methods of another class visible in one class. Multilevel inheritance is the term used for at least three classes that are connected in series. The concept is particularly suitable for rapid prototyping . On the one hand, you can manage the program code in separate classes, but at the same time you have a large class. Multilevel inheritance can be combined with multiple inheritance .
Covariance and contravariance
The handling of the variance in the signatures of overwritten methods is also related to the Liskovian substitution principle . Many programming languages do not allow variance, that is, the types of method parameters of overwritten methods must match exactly. The Liskov principle corresponds to the support of contravariance for input and covariance for output parameters. This means that input parameters can be more general than with the base class, and the type of return value can be more specific.
A few languages, the Declaration is exceptions (Engl. Exceptions ) permits that may occur when calling a method. The types of possible exceptions belong to the signature of a method. In Java and Modula-3 - the only two better-known languages that support such a thing - the set of possible exception types of an overridden method must be a subset of the original types, which means covariance and corresponds to the Liskovian substitution principle.
The design-by-contract concept, which Eiffel supports, is also related to the Liskov substitution principle . There is the possibility of defining preconditions and postconditions for methods as well as invariants for classes. The class variants as well as the post-conditions must be the same or more restrictive in specializations; the pre-conditions can be relaxed.
Data encapsulation as part of inheritance
When specifying the visibility of the attributes and methods of classes ( data encapsulation ), a distinction is often made as to whether the access takes place, for example, through a derived class or "from outside", i.e. when the class is used for other purposes. In most languages, a distinction is made between three cases:
- public (public) : The property is visible without restrictions
- protected (protected) : The property is, however, not in the class itself and for derived classes visible (more stages) from the outside.
- private (private) : The property is visible only in the class itself.
Not all languages support this three-part structure. Some of the boundaries of visibility are also designed differently. Java and the .NET languages also introduce variants that limit visibility to language-specific sub-units of the program structure (package or assembly ). In Ruby it has private
a different meaning: Private properties can also be accessed by specializing classes. However, access to properties of the same instance is basically only possible.
Another aspect of data encapsulation that is relevant to inheritance is the possibility of changing the visibility of properties in derived classes compared to the base class. For example in C ++ or Eiffel it is possible to restrict the visibility of all or individual properties when inheriting. In Java or the .NET languages, however, no such change in visibility is possible with inheritance.
Type conversion with static typing
Programming languages can be divided into those with static or dynamic typing . With dynamic typing, a type is not explicitly specified for variables and parameters . Smalltalk was the first object-oriented language with dynamic typing. In the case of static typing, on the other hand, it is indicated - usually by a declaration such as in Java - which type the value of a variable or parameter must have. In assignment or parameter passing can assignment compatibility of the types in this case already during compile time to be tested.
At every point where an object of a certain class is expected, an object belonging to a specialization of this class can also be used. For example, a variable of the type can PKW
always be Kraftfahrzeug
assigned to a variable of the type . However, after such an assignment, the additional properties of the specialization, in the example the number of seats, are not directly accessible. However, the object of the base class behaves like an object of the specializing class when calling virtual methods. Such a conversion is called an upcast .
The counterpart to this, a downcast , is more problematic, but necessary in some cases. Static typing languages usually also allow such a conversion, but this must be initiated explicitly. In this case, even with statically typing languages, it is only possible to check at runtime whether an object actually has the required type. Such a downcast, for example from Kraftfahrzeug
to PKW
, only makes sense if it is ensured that the object is actually of the type of the specific specialization. If no check is carried out and in this example an object that represents a truck is PKW
converted to the type , an exception is usually generated.
Programming languages with a central base class
Many object-oriented programming languages have a central class from which all classes - regardless of how many levels - are ultimately derived. For example, there is such a class in Ruby, Java and .NET. This is called for these languages Object
. In Eiffel it is ANY
called. The few exceptions where there is no such class are C ++ or Python.
In the languages with a central base class, a class for which no base class is specified implicitly inherits from that particular class. One advantage of this is that general functionality, for example for serialization or type information , can be accommodated there. It also enables the declaration of variables to which an object can be assigned to any class. This is particularly useful for implementing container classes when a language does not support generic programming . However, this method has the disadvantage that objects of any type can be added to such a general container. Since a special type is normally expected when an object in the container is accessed, a type conversion (downcast) is required. However, the corresponding type test can only be carried out at runtime.
Persistence in databases
In addition to simple serialization, storage in a database is the most common method of making objects persistent . Object-oriented databases aim to avoid what is known as an impedance mismatch , which occurs when the inheritance and object structure used in programming is mapped onto a relational database . However, object-oriented databases have not caught on until today, so that so-called object - relational mappers are often used.
A distinction is made between three options for the object-relational mapping of inheritance relationships:
- The attributes of all classes of a hierarchy are stored in a table (Single Table Inheritance)
- The attributes of each class are stored in a separate table (Class Table Inheritance)
- The attributes of each non- abstract class are stored in a separate table (Concrete Table Inheritance)
In the first variant (single table inheritance) , the type of the object must be stored in an additional column . The columns of the attributes that are not available for specific objects in the class hierarchy contain null values . Neither is necessary with the last two variants, the third variant is a kind of compromise.
In true object-oriented databases are essentially two opposite strategies are distinguished: persistence through inheritance (by Inheritance) and orthogonal persistence. With persistence through inheritance, the property of whether an object is transient or persistent depends on the type and is established through inheritance from a class that provides the functionality for connecting to the database. With orthogonal persistence, objects of the same class can be persistent as well as transient, so the property is completely independent of the type.
Inheritance in the context of software maintenance
Object-oriented elements and last but not least the inheritance mechanism have an expressiveness that has a very positive effect on the quality and comprehensibility of a system design. Comprehensive class libraries have emerged, the functionality of which can be adapted or expanded to suit the application using inheritance. Not least thanks to the inheritance mechanism, software systems can be built up modularly , which enables large systems to be controlled and, for example, also facilitates porting . However, unnecessarily deeply nested inheritance hierarchies increase the complexity and understanding considerably, which can lead to errors when using or changing the base classes.
In addition to the positive aspects, object-oriented programming has also shown negative aspects with regard to software maintenance , which are primarily related to polymorphism , but also to inheritance.
Supplement or adaptation of a class interface
Probably the most problematic case is the subsequent change to the interface of a central class, of which there are numerous specializations, for example in connection with the changeover to a new version of a class library. There are two main cases:
- Adding a new virtual method
- Adaptation of the signature of an existing virtual method or its renaming
If in the first case the new method is introduced without implementation, as part of an abstract class , all specializations must now provide this functionality when changing versions. However, it is far more serious if a virtual method of the same name already existed in the inheritance hierarchy in subordinate classes. This case cannot be detected by the compiler in most languages . This existing virtual method is now called in a context for which it was not implemented. If this problem is not eliminated by editing the version change documentation, it will lead to incorrect system behavior and usually to a runtime error .
In the second case, the renaming or signature adaptation must be carried out in the specializing classes. If this does not happen, the previous implementations are now "in the air", that is, they are no longer called at the required points, instead a standard functionality that exists in a base class is used, the originally intended adapted functionality is no longer implemented. In some constellations this problem cannot be detected by the compiler either.
Ensuring that such problems can be detected by the compiler actually requires a comparatively minor addition to a language. In C #, for example, this is covered by the keyword override
. This keyword must be specified for all methods that override a virtual method of the base class. The fact that such support is lacking in most languages such as C ++ or Java is due to the fact that this aspect was not adequately considered when the language was designed, and the subsequent introduction of such a keyword is met with considerable resistance due to major compatibility problems .
Fragile Base Class Problem
Even without changing a class interface, problems can arise when switching to a new version of a base class. In this case, the developers who change a “fragile” base class are unable to foresee the negative consequences of the change for specialized classes. The reasons for this are varied, essentially there is a misunderstanding between the developers of the base class and those of the specializations used. This is mostly due to the fact that the functionality of the base class and also the behavior expected by the specializations are not specified with sufficient precision.
A frequent cause of the fragile base class problem is the overly generous disclosure of implementation details, which is mostly done for practical reasons, whereby parts are also disclosed that are not yet fully developed in an initial version. The programming languages often do not facilitate the implementation of meaningful restrictions on the degrees of freedom; for example, methods in Java are basically virtual and must be final
marked as if it is not to be possible to overwrite them with a derived class.
Inheritance in prototype-based programming
The term inheritance is also used in prototype-based programming . In prototype-based languages, however, no distinction is made between class and instantiated object . Accordingly, inheritance does not mean exactly the same thing here, because a new object created by cloning "inherits" not only the structure of the original, also known as the parent , but also the content. The mechanism for using the methods of the parent by the copy (child) actually corresponds to a delegation . This can be used in the sense of inheritance, but has more degrees of freedom, for example in some such languages the addressee of the delegation - and thus the “base class” - can be exchanged at runtime.
literature
- Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Springer, London 2007, ISBN 1-84628-773-1 .
- Bernhard Lahres, Gregor Rayman: Practical book object orientation. From the basics to implementation . Galileo Press, Bonn 2006, ISBN 3-89842-624-6 .
- Klaus Zeppenfeld: Object-oriented programming languages. Introduction and comparison of Java, C ++, C #, Ruby . Spektrum Akademischer Verlag, Munich 2004, ISBN 3-8274-1449-0 .
- Ruth Breu: Object-oriented software design. Integration with UML . Springer, Heidelberg 2001, ISBN 3-540-41286-7 .
- Grady Booch , James Rumbaugh , Ivar Jacobson : The UML User Guide. Addison-Wesley, Bonn 1999, ISBN 3-8273-1486-0 .
- Jürgen Kunz: Inheritance for system developers. Basics and Applications . Vieweg, Braunschweig 1995, ISBN 3-528-05308-9 .
- Bertrand Meyer : Object-oriented software development . Hanser, Munich 1990, ISBN 3-446-15773-5 .
Individual evidence
- ^ Ole-Johan Dahl , Kristen Nygaard : Class and Subclass Declarations . In: JN Buxton (Ed.): Simulation Programming Languages . Proceedings of the IFIP working conference on simulation programming languages, Oslo, May 1967 North-Holland, Amsterdam, 1968, pages 158–174 ( online ( Memento of the original from June 10, 2007 in the Internet Archive ) Info: The archive link was inserted automatically and not yet checked. Please check the original and archive link according to the instructions and then remove this note .; PDF; 693 kB)
- ↑ Bjarne Stroustrup : Design and Development of C ++ . Addison-Wesley, Bonn 1994, ISBN 3-89319-755-9 , pages 90-98
- ↑ a b c Peter H. Fröhlich: Inheritance Decomposed . Inheritance Workshop, European Conference on Object-Oriented Programming (ECOOP), Málaga, June 11, 2002
- ↑ a b c d e Bertrand Meyer : The many faces of inheritance: A taxonomy of taxonomy . In: IEEE Computer , Vol. 29, 1996, pages 105-108
- ↑ Donald Smith Fire: Inheritance Guidelines . In: Journal of Object-Oriented Programming . 8 (2), 1995, pp. 67-72
- ↑ see for example: MSDN , .NET Framework Class Library: ISerializable Interface
- ↑ see for example: Java 2 Platform, Standard Edition, v 1.4.2, API Specification: Interface Comparable ( Memento of the original from March 23, 2009 in the Internet Archive ) Info: The archive link was automatically inserted and not yet checked. Please check the original and archive link according to the instructions and then remove this notice.
- ↑ Ruth Breu: Object-oriented software design . Page 198f, see literature
- ↑ a b c d Bernhard Lahres, Gregor Rayman: Practical book object orientation . Pages 153–189, see literature
- ↑ Christoph Schmitz: Specification of Object-Oriented Systems University of Tübingen, 1999, pp. 9–12
- ^ An exception is Sather , see Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Page 187, see literature
- ^ A b Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Pages 185–190, see literature
- ^ Alan Snyder: Inheritance and the development of encapsulated software systems . In: Research Directions in Object-Oriented Programming . Cambridge. 1987, pp. 165-188
- ^ A b Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Pages 91-98, see literature
- ^ A b Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Pages 98–124, see literature
- ^ David Thomas , Andrew Hunt : Programming Ruby. The Pragmatic Programmer's Guide . Addison-Wesley Longman, Amsterdam 2000, ISBN 0-201-71089-7 , pages 99-104 ( online )
- ↑ a b Bjarne Stroustrup: Design and Development of C ++ . Addison-Wesley, Bonn 1994, ISBN 3-89319-755-9 , pages 327-352
- ^ Bertrand Meyer: Object-oriented software development . Pages 296–300, see literature
- ↑ Florian Adamsky: Inheritance and polymorphism . In: Technische Hochschule Mittelhessen, software development in SS 2014 . 2014 ( adamsky.it [PDF]).
- ↑ Kuruvada, Praveen and Asamoah, Daniel and Dalal, Nikunj and Kak, Subhash: The Use of Rapid Digital Game Creation to Learn Computational Thinking . 2010, arxiv : 1011.4093 .
- ↑ Manoj Kumar Sah and Vishal Garg: Survey on Types of Inheritance Using Object Oriented Programming with C ++ . In: International Journal of Computer Techniques . tape 1 , 2014 ( ijctjournal.org [PDF]).
- ^ Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Pages 174–179, see literature
- ^ Anna Mikhailova, Alexander Romanovsky: Supporting Evolution of Interface Exceptions . (PDF; 167 kB) In: Advances in exception handling techniques . Springer-Verlag, New York 2001, ISBN 3-540-41952-7 , pages 94-110.
- ↑ B. Meyer: Object-oriented software development . Pages 275–278, see literature
- ^ A b Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Pages 25–31, see literature
- ↑ Bernhard Lahres, Gregor Rayman: Praxisbuch object orientation . Pages 103–110, see literature
- ↑ Bernhard Lahres, Gregor Rayman: Praxisbuch object orientation . Pages 90-99, see literature
- ^ Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Page 179ff, see literature
- ^ Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Page 173f, see literature
- ↑ Bernhard Lahres, Gregor Rayman: Praxisbuch object orientation . Pages 300–307, see literature
- ↑ a b Bernhard Lahres, Gregor Rayman: Practical book object orientation . Pages 307-320, see literature
- ↑ Asbjørn Danielsen: The Evolution Of Data Models And Approaches To Persistence In Database Systems , University of Oslo , 1998
- ↑ a b c d e Erhard Plödereder: OOP language constructs in the context of software maintenance . Lecture at the industrial software production conference , Stuttgart 2001
- ^ Victor R. Basili , Lionel Briand, Walcélio L. Melo: A Validation of Object-Oriented Design Metrics as Quality Indicators . In: University of Maryland, Department of Computer Science (Ed.): IEEE Transactions on Software Engineering . tape 22 , no. 10 , October 1996, p. 751-761 (English).
- ↑ Jeff Offut, Roger Alexander: A Fault Model for Subtype Inheritance and Polymorpism . ( Memento of the original from August 3, 2007 in the Internet Archive ) Info: The archive link was inserted automatically and has not yet been checked. Please check the original and archive link according to the instructions and then remove this notice. (PDF; 119 kB) In: The Twelfth IEEE International Symposium on Software Reliability Engineering. Hong Kong 2001, pp. 84-95
- ↑ Bernhard Lahres, Gregor Rayman: Praxisbuch object orientation . Pages 238–257, see literature
- ↑ Leonid Mikhajlov, Emil Sekerinski: A Study of The fragile base class . ( Memento of the original from April 4, 2014 in the Internet Archive ) Info: The archive link was inserted automatically and has not yet been checked. Please check the original and archive link according to the instructions and then remove this notice. (PDF; 518 kB) In: Proceedings of the 12th European Conference on Object-Oriented Programming , 1998, ISBN 3-540-64737-6 , pages 355-382
- ↑ Joshua Bloch : Effective Java . Addison-Wesley, 2008, ISBN 0-321-35668-3 , pages 87-92
- ^ Iain D. Craig: Object-Oriented Programming Languages: Interpretation . Pages 57–72, see literature
Remarks
- ↑ The modeling is used here for illustration purposes only. For example, attributes such as the type of drive, displacement and whether a trailer is carried would also have to be taken into account in a realistic system.
- ↑ The set of possible characteristics of the subtype still forms a subset of the basic type if only the attributes of the basic type are considered.
- ↑ In practice, such a change can be made retrospectively and without the developer of the base class and the derived class having to know each other, for example when using a class library and switching to a new version.
- ↑ This aspect is one reason why such specialization is unfavorable in some use cases. This example is often used for illustration and discussion of this related to the inheritance problem and is also known as Ellipse problem area (circle ellipse problem) known.
- ↑ In Java, however, this principle only applies to some of the possible exception types , the so-called checked exceptions .
- ↑ With C ++ or Java, on the other hand, access to private properties of other instances of the same class is possible, which is typically exploited in the copy constructor by direct access to the properties of the source object.
- ↑ However, this is not true for C ++ if the assignment is at the value level.
- ↑ In Java, generic programming was only supported from version 1.5, for .NET only with the .NET Framework 2.0. Previously, the implementation of the container classes was based exclusively on this principle.
-
↑ In Java Version 1.5 an annotation was
@Override
introduced, which only partially solves the problem, especially since it does not have to be used.
Web links
- Axel Schmolitzky: A model for separating inheritance and type abstraction in object-oriented languages. ( PDF; 1.9 MB ) Ulm University
- A Critical Look at Inheritance . (English; PDF; 37 kB ) University of Cyprus