Inheritance
Inheritance is one basic feature of OOP:
Subclass inherits from Superclass
Properties and methods of a superclass can be "inherited" by subclasses, which means subclasses have them as well respectivly reuse them (so-called "code reuse").
Inheritance, the third type of relationship between objects, represents an "is an" association.
(Composition and aggregation, on the other hand, are "has an" associations.)
In the following example, a customer is a person.
Class Customer is derived from class Person
To be able to access the properties inherited from the superclass in the subclass, the properties in the superclass must be declared protected:
1 public class Person { // Definition of superclass 2 3 protected String name; // access modifier protected -> access to member is 4 // possible in subclass as well 5 6 public Person() { 7 System.out.println("Default constructor of superclass Person"); 8 } 9 public Person(String name) { 10 this.name = name; 11 System.out.println("parameterized constructor of superclass Person"); 12 } 13 14 public String getName() { 15 return name; 16 } 17 public void setName(String name) { 18 this.name = name; 19 } 20 }
The subclass Customer inherits all the properties and methods of the superclass Person. Therefore, they need not be redefined. The code is "reused".
In subclasses, only the additions to the superclass have to be defined:
1 public class Customer extends Person{ //Subclass inherits from the superclass Person 2 3 private int customerNumber; 4 5 public Customer(String name) { 6 this.name = name; 7 System.out.println("parameterized constructor of subclass Customer"); 8 } 9 10 public int getCustomerNumber() { 11 return customerNumber; 12 } 13 public void setCustomerNumber(int customerNumber) { 14 this.customerNumber = customerNumber; 15 } 16 }
Creation of objects and access are done as usual:
1 public class Main { 2 3 public static void main(String[] args) { 4 Person p = new Person("Person"); 5 System.out.println(p.getName() + "\n"); 6 7 Customer c = new Customer("Customer"); 8 c.setCustomerNumber(1); 9 System.out.println(c.getName() + "\t" + c.getCustomerNumber()); 10 } 11 }
The output of the program is:
Parameterized Constructor of superclass Person
Person
Default Constructor of superclass Person
Parameterized Constructor of subclass Customer
Customer 1
It can be seen, when the object of subclass is created, first the constructor of the superclass and after that the constructor of the subclass is invoked. How can this be explained?
Nested objects
The object of subclass contains the superclass object. That means the superclass object is a part of the subclass object:
Object of the inheriting class contains object(s) of the superclass
For this reason, all constructors must be invoked sequentially from the inside to outside, i.e. starting with the superclass up to the last subclass.
Consequences for type conversions
Subclass objects can be converted to superclass objects, because unnecessary attributes and methods are simply removed.
Person p2 = c; // implicit type conversion is possible
// because all fields and methods (members) of the person object are defined System.out.println(p2.getName()); System.out.println(p2.getCustomerNumber()); // not possible because an object of
// class Person has no customerNumber
Customer
Of course, typecasting loses all the extra properties and methods of the subclass. Only the inner object is preserved.
An explicit type conversion in this direction is possible and does the same:
Person p2 = (Person)c; // also explicit type conversion in this direction is possible
On the other hand, a superclass object can not be converted to an object of the subclass:
Customer c2 = p;// reversed direction not possible
The additional members of the subclass would all be undefined.
Even the attempt of an explicit typecast in this direction fails. It raises an ClassCastException at runtime:
Customer c2 = (Customer)p;// reversed direction not possible
Interestingly, this explicit transformation is possible:
Customer c2 = (Customer)p2; // possible because p2 actually contains a referenceThe above type conversion from object
// to a object of class Customer.
k to object p2 actually only converted the type of the reference, not the object itself. This is a basic prerequisite for the concept of so-called polymorphism.