1. Technology

How to Prevent Inheritance

By

There can be times when designing a class when it's desirable to prevent inheritance by another class. These situations arise when a class is likely to be used by other programmers and any subclasses created could cause problems.

A typical example is the String class. If I wanted to try and make a String subclass:

 public class MyString extends String{
 
 } 

I will be faced with this error:

 cannot inherit from final java.lang.String 

The designers of the String class realized that it was not a candidate for inheritance and have prevented it from being extended.

Why Prevent Inheritance?

The main reason to prevent inheritance is to make sure the way a class behaves is not corrupted by a subclass. Previously I've used this example to show how a subclass can be treated as a superclass:

 Account bobsAccount = new Account(10);
 bobsAccount.depositMoney(50);

 OverdraftAccount jimsAccount = new OverdraftAccount(15.05,500,0.05);
 jimsAccount.depositMoney(50);

 //create an array of Account objects
 //we can include jimsAccount because we 
 //only want to treat it as an Account object
 Account[] accounts = {bobsAccount, jimsAccount};
 
 //for each account in the array display the balance
 for (Account a:accounts)
 {
   System.out.printf("The balance is %.2f%n", a.getBalance());
 }

 The output is:
 The balance is 60.00
 The balance is 65.05 

The OverdraftAccount class is a subclass of the Account class and it does not override the behavior getBalance. However, there is nothing to prevent it from doing so:

 public class OverdraftAccount extends Account {
 
   private double overdraftLimit;
   private double overdraftFee;
 
   //the rest of the class definition is not included
 
   public double getBalance()
   {
     return 25.00;
   }
 } 

If the example code above is executed again, the output will be different because the getBalance behavior in the OverdraftAccount class is called for jimsAccount:

 The output is:
 The balance is 60.00
 The balance is 25.00 

Unfortunately now the subclass OverdraftAccount will never give the correct balance because I have corrupted the behavior of the Account class through inheritance. If you design a class to be used by other programmers always consider the implications of any potential subclasses. This is the reason the String class cannot be extended. It's extremely important that programmers know that when they create a String object it's always going to behave like a String.

How to Prevent Inheritance

To stop a class being extended, the class declaration must explicitly say it cannot be inherited. This is achieved by using the "final" keyword:

 public final class Account {
 
 } 

This means that the Account class cannot be a superclass and the OverdraftAccount class can no longer be its subclass.

Sometimes it's the case that there are only certain behaviors of a superclass that we don't want to be corrupted by a subclass. For example with the bank account classes, OverdraftAccount still needs to be a subclass of Account, but it should be prevented from overriding the getBalance behavior. In this case the "final" keyword can be used in the method declaration:

 public class Account {
 
   private double balance;
 
   //the rest of the class definition is not included
 
   public final double getBalance()
   {
     return this.balance;
   } 
 } 

Notice how the final keyword is not used in the class definition. Subclasses of Account can be created but they can no longer override the getBalance behavior. Any code calling that behavior of an object can be confident it will work as the original programmer intended.

©2014 About.com. All rights reserved.