ZOFTINO.COM android and web dev tutorials

Inheritance in Java

In Java, a class can be created by using another related class so that the fields and methods of the other class can be available in the new class without repeating the field and method declarations. The capability of deriving a class from another class is called inheritance and the class which is created using another class is called subclass and the class which is used to create another class is called super class.

Table of Contents

Introduction to Inheritance

A class can inherit member fields, methods and nested classes of another class by extending it. The class which is being extended by other class is called base class, parent class or super class. The class which extends other class is called child class or sub class. All the base classes implicitly inherit Object class. All classes are sub classes of Object.

public class Offer {
	
	private int offer;
	private int type;
	
	public int getOffer() {
		return offer;
	}
	public void setOffer(int offer) {
		this.offer = offer;
	}
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	
	public double getOfferAmount(double billAmount) {
		if(type  == 0) {
			return billAmount*offer/100;
			
		}
		return offer;		
	}
}

Here is a sub class of Offer base class. Example shows that subclass Coupon inherits members of Offer and doesn’t need to define them again in it. For example getOffer() method is available in subclass Coupon.

public class Coupon extends Offer{
	private String couponCode;	

	public String getCouponCode() {
		return couponCode;
	}

	public void setCouponCode(String couponCode) {
		this.couponCode = couponCode;
	}
	public String printCoupon() {
		String coupon = "Coupon "+getOffer()+ " off " + couponCode;
		return coupon;
	}
}

Super class method can be invoked on subclass instance.

		Coupon cpn = new Coupon();
		cpn.setOffer(20);
		cpn.setType(0);
		
		cpn.getOfferAmount(5000);

Super Class Constructors

Subclasses don’t inherit constructors from super class. But they can call super class constructor to reuse the code of super class constructor for initializing members of super class. Super class constructor can be called using super key word.

public class Offer {
	
	private int offer;
	private int type;
	
	public Offer() {
		
	}
	
	public Offer(int offer, int type) {
		this.offer = offer;
		this.type = type;
	}
…}
public class Coupon extends Offer{

	public Coupon(int offer) {
		super(offer, 0);
	}
…}

If a super class defines a constructor with parameters and doesn’t provide default or no argument constructor, then subclass must call super class constructor from all the constructors it defines otherwise you will get compiler error. You won’t get compiler error if super class has default constructor because Java compiler automatically inserts a call to super class default constructor in subclass constructors.

For example, Offer class has one constructor which takes parameters.

public class Offer {
	public Offer(int offer, int type) {
		this.offer = offer;
		this.type = type;
	}
...
}

All constructors of Coupon class calls super class constructors.

public class Coupon extends Offer{
	public Coupon() {
		super(5, 0);
	}
	public Coupon(int offer, int type) {
		super(offer, type);
	}
	public Coupon(int offer) {
		super(offer, 0);
	}
…}

When a subclass is instantiated, constructor of it super class and constructor of super class’s super class, so on are called till constructor of object is called leading to constructor chaining.

Impact of Access Modifiers on Inheritance

Who can access members of a class can be controlled using access modifiers. Subclass doesn’t inherit private members. It inherits public and protected members of the super class. It also inherits default or package private members if parent exists in the same package as subclass.

Here is a super class with private, default, protected and public members.

public class Loan {
	private String ssn;
	double loanAmount;
	protected int offerdablePct;
	public double interest;
	
	
	public String getSsn() {
		return ssn;
	}
	public void setSsn(String ssn) {
		this.ssn = ssn;
	}
	public double getLoanAmount() {
		return loanAmount;
	}
	public void setLoanAmount(double loanAmount) {
		this.loanAmount = loanAmount;
	}
	public int getOfferdablePct() {
		return offerdablePct;
	}
	public void setOfferdablePct(int offerdablePct) {
		this.offerdablePct = offerdablePct;
	}
	public double getInterest() {
		return interest;
	}
	public void setInterest(double interest) {
		this.interest = interest;
	}	
}

Subclass HomeLoan of Loan class can access protected, default and public member fields offerdablePct, loanAmount and interest respectively of Loan class.

public class HomeLoan extends Loan{
	private double propertyValue;
	private double downPayment;
	private double monthlyIncome;
	
	public double calculateOfferableEmi() {
		return offerdablePct*monthlyIncome/100;
	}
	
	public double getBestLoanTenure() {
		return loanAmount + (loanAmount*interest/100) /calculateOfferableEmi();
	}
	
	public void setLoanAmt() {
		loanAmount = propertyValue - downPayment;
	}

	public void setPropertyValue(double propertyValue) {
		this.propertyValue = propertyValue;
	}

	public void setDownPayment(double downPayment) {
		this.downPayment = downPayment;
	}

	public void setMonthlyIncome(double monthlyIncome) {
		this.monthlyIncome = monthlyIncome;
	}
	
}

Defining Same Members in Subclass

Member fields of the super class can be hidden in subclasses by defining the fields with the same name as they are in super class.

public class ClassA {
	protected String hello = "hello";

	public String getHello() {
		return hello;
	}

	public void setHello(String hello) {
		this.hello = hello;
	}
	
}

Member field hello is declared in subclass hiding the one declared in super class.

public class ClassB extends ClassA {
	private String hello = "hi";

	public String getHello() {
		return hello;
	}

	public void setHello(String hello) {
		this.hello = hello;
	}
}
		ClassA a =  new ClassA();		
		ClassB b = new ClassB();		
		
		System.out.println("ClassA : "+a.getHello());
		System.out.println("ClassB : "+b.getHello());
ClassA : hello
ClassB : hi

The process of defining in subclasses the methods whose signature match to non static methods of super class is called method overriding, see object oriented programming concepts for more details and example. You can change the access modifier of overriding methods in sub class to the ones which allow more access than the modifiers used in the super class.

A static method in super class can be hidden by defining a static method in the sub class with same signature. For example, static method printString() in ClassB is created with same signature as it is in ClassA.

public class ClassA {
	public static void printString(String str) {
		System.out.println("ClassA : "+str);
	}
}
public class ClassB extends ClassA {
	public static void printString(String str) {
		System.out.println("ClassB : "+str);
	}
}

When the method is invoked on ClassB, the version defined in ClassB is called hiding ClassA implementation. So the version that is called depends on which class it is invoked on.

		ClassA.printString("Hello printer");
		ClassB.printString("Hello printer");

Output:

ClassA : Hello printer
ClassB : Hello printer

Casting

Casting allows you to assign an object of a sub class in a hierarchy to a variable type of any super class in the hierarchy and convert super class type to sub class type.

For example, take our Loan class hierarchy. An instance of subclass can be assigned to a variable of super class type. This assignment implicitly casts subclass type to super class.

Loan loan = new HomeLoan();

Whereas, assigning variable of super class to subclass type needs explicit casting otherwise you will get compile time error saying type mismatch : can’t convert …

Loan loan = new HomeLoan();
HomeLoan hl = (HomeLoan)loan;

Super class type may reference to an instance of super class and casting that to subclass type lead to runtime class cast exception.

HomeLoan hl = (HomeLoan) new Loan();

To prevent class cast exception, you need to check whether a type is referencing to an instance of a particular class using instanceof operator and then do the explicit casting.

		HomeLoan hl;
		if(loan instanceof HomeLoan) {
			hl = (HomeLoan)loan;
		}

Method Overriding and Polymorphism

Please see object oriented programming concepts for details and example.

Super Keyword

Super keyword is used to refer to super class constructors and methods. Below example shows a method in subclass uses super to call the same method in the super class.

public class Loan {
	private String ssn;
	double loanAmount;
	public double interest;
	
	public String toString() {
		return ssn+" "+loanAmount+" "+interest;
	}
}
public class HomeLoan extends Loan{
	private double propertyValue;
	private double downPayment;
	private double monthlyIncome;
	
	public String toString() {
		String superStr = super.toString();
		return superStr + " "+propertyValue+" "+
				downPayment+" "+monthlyIncome;
	}
}

Final Classes

To prevent other classes from extending a class, a class can be declared as final. You will get compiler error if you try to extend final class.

final public class Loan {

}

Final Methods

To prevent methods defined in super class from being overridden, you can declare methods as final. Any base functionality that should be applicable as is to all sub classes in the hierarchy can be declared as final.

 public class Loan {
	final public String getLoanDesc(String loan) {
		return "xyz bank loan product "+loan;
	}	
}

Abstract Classes and Methods

A method can be declared without body in the class. Such method is called an abstract method. If a class contains an abstract method, it should be declared as abstract class.

public abstract class Loan {
	abstract public String getLoanDesc(String loan);
}

You can prevent a class from instantiating it by declaring the class as abstract even if it doesn’t have abstract methods.

Multiple Inheritance

Java doesn’t support multiple inheritance meaning a class can’t extend more than one class to prevent the ambiguity arises out multiple inheritance of state and multiple inheritance of implementations when the classes being extended have common fields and methods.

Java supports multiple inheritance of type meaning a class can implement multiple interfaces, as interface doesn’t contain instance fields.

public interface PlanFeaturesProvider {
	List<String> getFeatures();
	String getPlanType();
}
public interface PhoneFeaturesProvider {
	List<String> getFeatures();
	String getPhoneType();	
}

DefaultFeatureProvider class implements both PhoneFeaturesProvider, PlanFeaturesProvider interfaces and provide implementation of all methods including common method of those interfaces.

public class DefaultFeatureProvider implements
					PhoneFeaturesProvider, PlanFeaturesProvider  {
	
	public List<String> getFeatures(){
		List<String> fl = new ArrayList<String>();
		fl.add("Roaming free");
		fl.add("All device sensors");
		return fl;
	}

	@Override
	public String getPlanType() {
		return "data";
	}

	@Override
	public String getPhoneType() {
		return "smart";
	}
}

But Java8 introduced default methods which can be defined with body in interfaces. With multiple inheritance of type, class can inherit default methods. If there are common default methods in the interfaces which a class implements, you have to override the common default method and provide behavior. Please see how common default method is handled in an interface which extends multiple interfaces with common default method.

Here is an example of multiple inheritance of type with common default method.

public interface PlanFeaturesProvider {
	default List<String> getFeatures(){
		List<String> fl = new ArrayList<String>();
		fl.add("Roaming free");
		return fl;
	}
}
public interface PhoneFeaturesProvider {
	default List<String> getFeatures(){
		List<String> fl = new ArrayList<String>();
		fl.add("All device sensors");
		return fl;
	}
}
public class DefaultFeatureProvider implements
					PhoneFeaturesProvider, PlanFeaturesProvider  {
	
	public List<String> getFeatures(){
		List<String> fl = PhoneFeaturesProvider.super.getFeatures();
		fl.addAll(PlanFeaturesProvider.super.getFeatures());
		return fl;
	}
}

Differences between Class and Interface

Please read Java Classes and Object and Java Interface to understand classes and interface. Here are the differences between classes and interfaces.

  • Class can have instance fields whereas interface can’t have instance fields.
  • Both classes and interfaces can have constants.
  • Both classes and interfaces can contain static methods.
  • Both classes and interfaces can contains abstract methods. If a class contains an abstract method, which is called abstract class.
  • Classes contain method implementations. Whereas interface contains default methods.
  • Classes can be instantiated but interfaces can’t be instantiated.
  • A class can extend only one class whereas interface can extend multiple interfaces.
  • Classes provide body for all the methods defined in an interface by implementing the interface.
  • A Class can implement multiple interfaces.
  • An instance of a class which implements an interface can be assigned to a variable of the interface type.

Comparison of Interface and Abstract Class

  • Both abstract classes and interfaces can’t be instantiated.
  • Abstract class can contain non static and non final fields where as interface can contains only static final fields.
  • Both abstract classes and interfaces can contain methods with body. The methods in interface which contain body are called default methods.
  • Abstract class can contain public, protected, private methods whereas interface can contain only public methods.
  • A class can extend only one abstract class whereas it can implement multiple interfaces.
  • If all abstract methods of an abstract class are not implemented in a class which extends the abstract class, it should be declared as abstract class.
  • If all methods of an interface are not implemented by a class which implements the interface, then the class should be declared as abstract.