Tuesday, May 26, 2020

Using the Keyword Final with Inheritance in Java

While one of Javas strengths is the concept of inheritance, in which one class can derive from another, sometimes its desirable to prevent inheritance by another class. To prevent inheritance, use the keyword final when creating the class. For example, if a class is likely to be used by other programmers, you may wish to prevent inheritance if any subclasses created could cause problems. A typical example is the String class. If we wanted to create a String subclass: public class MyString extends String{ï » ¿} We would 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. Suppose we have a class Account and a subclass that extends it, OverdraftAccount. Class Account has a method getBalance(): public double getBalance(){ return this.balance; } At this point in our discussion, subclass OverdraftAccount has not overridden this method. (Note: For another discussion using this Account and OverdraftAccount classes, see how a subclass can be treated as a superclass). Lets create an instance each of the Account and OverdraftAccount classes: 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 Everything appears to work as expected, here. But what if OverdraftAccount overrides the method getBalance()? There is nothing to prevent it from doing something like this: 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, the subclass OverdraftAccount will never provide the correct balance because we 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. Its extremely important that programmers know that when they create a String object, its always going to behave like a String. How to Prevent Inheritance To stop a class from 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, you may wish to limit only certain behaviors of a superclass to avoid corruption by a subclass. For example, OverdraftAccount still could be a subclass of Account, but it should be prevented from overriding the getBalance() method. In this case use, the final keyword 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() method. Any code calling that method can be confident it will work as the original programmer intended.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.