07. Java Inheritance (Part 1)
InheritanceIn Java, you may create subclasses that reuse and extend another class, so that the subclass inherits (has direct access to) certain members (variables & methods) of its superclass. (A Java subclass is like a C++ derived class).
Why is inheritance useful? The design of a program is better when you create classes for more general features, and subclasses for more detailed features. We'll see some examples of this later.
What's different about subclasses from a regular class?
- when an object of a subclass is instantiated, all of the instance variables in the superclass (and its superclass, etc.) are allocated memory along with the subclass' instance variables
- non-private* methods in its superclass (and its superclass, etc.) may be called on a subclass object, as well as the subclass' (non-private) methods
- when inside a subclass instance method, the superclass (non-private) methods may be called (if the superclass method is not overriden in the subclass)
- when inside a subclass instance method, the superclass (non-private) variables may be directly accessed (unless the subclass has a variable with the same name)
Differences from C++:
- Java does NOT support multiple inheritance, i.e., each class may only haveone superclass (unlike C++).
- Java allows implementing more than one interface (see p. 16).
- Every Java class may be subclassed unless it is declared as final.
- The default superclass for all classes isjava.lang.Object (details later)
*Non-private methods include public, protected or no access specifier (protected superclass members are accessible by methods of a subclass in the same or different package and non-subclasses in the same package)
Defining a Subclass
In the class heading, add the extends class: class subclass-id extends superclass-id
Optional: You may define the class as public
Examples:
public class SuperClass{
int packageVar;
public int publicVar;
private int privateVar;
protected int protectedVar;
} // end class SuperClass
public class SubClass1 extends SuperClass{
void someMethod(){
packageVar = 0; // OK if in same package
publicVar = 0; // OK
privateVar = 0; // Error
protectedVar = 0; // OK
}
} // end class SubClass1
// In another package:
public class SubClass2 extends SuperClass{
void someMethod(){
packageVar = 0; // Error
publicVar = 0; // OK
privateVar = 0; // Error
protectedVar = 0; // OK
}
} // end class SubClass
public class Main{
public static void main( String [] args ){
SubClass1 sub1 = new SubClass1();
sub1.packageVar = 0; // Error
sub1.publicVar = 0; // OK
sub1.privateVar = 0; // Error
sub1.protectedVar = 0; // Error
SubClass2 sub2 = new SubClass2();
sub2.packageVar = 0; // Error
sub2.publicVar = 0; // OK
sub2.privateVar = 0; // Error
sub2.protectedVar = 0; // Error
} // end main
} // end class Main
NOTE: When no access specifier is given for a class, method or variable, then it can only be accessed by all methods in the same package.
More on Subclasses
Inside a Subclass:
- In the subclass' constructor(s) you may call a superclass constructor just by doing (must be thefirst statement in the subclass' constructor): super( parameters);
- NOTE: If you DON'T explicitly call the superclass constructor, then the JVM will try to call its default constructor (which may not exist)!
- You may call a superclass non-private method if no method in the subclass has the same name by calling as if it’s in the same class
- You may override a superclass method in the subclass (defining it with the exact same name and same parameters)-- this triggers polymorphism(read more about polymorphism HERE)
- If the superclass has the same name method as in the subclass, to call it, do: super.method-id(parameters)
- You may assign a subclass object (reference) to a superclass object variable
- When a subclass constructor passes a parameter up to the superclass constructor via the superkeyword, the parameter cannot be a class-scope instance variable of the subclass because the subclass hasn't been constructed yet. Example extending the Grandparent class on next page:
public class BadParent extends Grandparent{
private int data=1;
public BadParent(){
super(data); // Error: can't pass data
}
} // end class BadParent
Example of Using Inheritance
public class Grandparent{
protected int data;
public Grandparent(int i){
data=i;
} // end Grandparent constructor
public void display(){
System.out.println("Grandparent display "+data);
} // end display method
} // end Grandparent class
public class Parent
extends Grandparent{
protected int data; // different from Grandparent's
public Parent( int i ){
super( i+1 ); // calls Grandparent constructor
data=i;
} // end Parent constructor
public void display(){
System.out.println("Parent display "+data);
} // end display method
} //end Parent class
public class Child
extends Parent{
protected int data; // different from Parent's
public Child( int i ){
super( i+1 ); // calls Parent constructor
data = i;
} // end Child constructor
public void display(){
System.out.println("Child display" + this.data);
System.out.println("Parent data = " +
super.data);
System.out.println("Grandparent data= " +
((Grandparent)this).data );
super.display();
// Note: Can't call Grandparent's display()
// from here even with casting
} // end display method
} // end Child class
Note: (Grandparent) in the above example is casting the Child reference to its Grandparent.
In another class and file:
public class TryInheritance
{
public static void main( String[] args )
{
Grandparent g = new Grandparent( 100 );
Parent p1 = new Parent( 10 );
Parent p2;
Child c1 = new Child( 1 );
Child c2;
p2 = c1; // example of assigning a subclass obj. to superclass var.
if( p2 instanceof Child )//always check
c2 = (Child) p2;
//NOTE: if you downcast and it isn't an instance,
// an exception will be thrown
g.display();// displays "Grandparent display 100"
p1.display();// displays "Parent display 10"
p2.display();// displays "Child display 1", etc.
c1.display();// displays "Child display 1", etc.
} // end main
} // end TryInheritance