[7.1] Describe inheritance and its benefits
[7.5] Use abstract classes and interfaces
When we discuss inheritance in the context of an object-oriented programming language such as Java, we talk about how a class can inherit the properties and behavior of another class. The class that inherits from another class can also define additional properties and behaviors. The exam will ask you explicit questions about the need to inherit classes and how to implement inheritance using classes.
Let’s get started with the need to inherit classes.
Imagine the positions Programmer and Manager within an organization. Both of these positions have a common set of properties, including name, address, and phone number. These positions also have different properties. A Programmer may be concerned with a project’s programming languages, whereas a Manager may be concerned with project status reports.
Let’s assume you’re supposed to store details of all Programmers and Managers in your office. Figure 6.1 shows the properties and behavior that you may have identified for a Programmer and a Manager, together with their representations as classes.
Did you notice that the classes Programmer and Manager have common properties, namely, name, address, phoneNumber, and experience? The next step is to pull out these common properties into a new position and name it something like Employee. This step is shown in figure 6.2.
This new position, Employee, can be defined as a new class, Employee, which is inherited by the classes Programmer and Manager. A class uses the keyword extends to inherit a class, as shown in figure 6.3.
Inheriting a class is also referred to as subclassing. In figure 6.3, the inherited class Employee is also referred to as the superclass, base class, or parent class. The classes Programmer and Manager that inherit the class Employee are called subclasses, derived classes, extended classes, or child classes.
Why do you think you need to pull out the common properties and behaviors into a separate class Employee and make the Programmer and Manager classes inherit it? The next section covers the benefits of inheriting classes.
Do you know that all classes in Java inherit class java.lang.Object, either implicitly or explicitly? Extending a class offers multiple benefits. Let’s revisit the examples used in the previous section to highlight the benefits of inheriting classes.
What if you were supposed to write more-specialized classes, such as Astronaut and Doctor, which have the same common characteristics and behaviors as those of the class Employee? With the class Employee in place, you’d only need to define the variables and methods that are specific to the classes Astronaut and Doctor and have the classes inherit Employee.
Figure 6.4 is a UML representation of the classes Astronaut, Doctor, Programmer, and Manager, both with and without inheritance from the class Employee. As you can see in this figure, the definition of these classes is smaller when they inherit the class Employee.
The examples used in this book are simplified and generalized so that you can focus on the concept being covered. They don’t take into consideration all real-world scenarios. For example, on a particular project, an astronaut or a doctor might not be an employee of some organization.
What happens if your boss steps in and tells you that all of these specialized classes—Astronaut, Doctor, Programmer, and Manager—should now have a property facebookId? Figure 6.5 shows that with the base class Employee in place, you just need to add this variable to that base class. If you haven’t inherited from the class Employee, you’ll need to add the variable facebookId to each of these four classes.
Note that common code can be modified and deleted from the base class Employee fairly easily.
Code that works with the base class in a hierarchy tree can work with all classes that are added using inheritance later.
Assume that an organization needs to send out invitations to all its employees and that it uses the following method to do so:
class HR { void sendInvitation(Employee emp) { System.out.println("Send invitation to" + emp.name + " at " + emp.address); } }
Because the method sendInvitation accepts an argument of type Employee, you can also pass to it a subclass of Employee. Essentially, this design means that you can use the previous method with a class defined later that has Employee as its base class. Inheritance makes code extensible.
You don’t need to reinvent the wheel. With inheritance in place, subclasses can use tried-and-tested code from a base class.
Inheriting a class enables you to concentrate on the variables and methods that define the special behavior of your class. Inheritance lets you make use of existing code from a base class without having to define it yourself.
When multiple classes inherit a base class, this creates a logical group. For an example, see figure 6.5. The classes Astronaut, Doctor, Programmer, and Manager are all grouped as types of the class Employee.
Inheritance enables you to reuse code that has already been defined by a class. Inheritance can be implemented by extending a class.
The next section solves the mystery of how you can access the inherited members of a base class directly in a derived class.
The classes Programmer and Manager inherit the nonprivate variables and methods defined in the class Employee and use them directly, as if they were defined in their own classes. Examine the following code:
How can the class Programmer assign a value to a variable that’s defined in the class Employee? You can think of this arrangement as follows: When a class inherits another class, it encloses within it an object of the inherited class. Hence, all the nonprivate members (variables and methods) of the inherited class are available to the class, as shown in figure 6.6.
But a derived class can’t inherit all the members of its base class. The next two sections discuss which base class members are and aren’t inherited by a derived class.
The access modifiers play an important role in determining the inheritance of base class members in derived classes. A derived class can inherit only what it can see. A derived class inherits all the nonprivate members of its base class. A derived class inherits base class members with the following accessibility levels:
A derived class can inherit only what it can see.
A derived class doesn’t inherit the following members:
Apart from inheriting the properties and behavior of its base class, a derived class can also define additional properties and behaviors, as discussed in the next section.
Although derived classes are similar to their base classes, they generally also have differences. Derived classes can define additional properties and behaviors. You may see explicit questions on the exam about how a derived class can differ from its base class.
Take a quick look back at figure 6.5. All the derived classes—Manager, Programmer, Doctor, and Astronaut—define additional variables, methods, or both. Derived classes can also define their own constructors and static methods and variables. A derived class can also hide or override its base class’s members.
When a derived class defines an instance or class variable with the same name as one defined from its base class, only these new variables and methods are visible to code using the derived class. When a derived class defines different code for a method inherited from a base class by defining the method again, this method is treated as a special method—an overridden method.
You can implement inheritance by using either a concrete class or an abstract class as a base class, but there are some important differences that you should be aware of. These are discussed in the next section.
Figures 6.2 and 6.3 showed how you can pull out the common properties and behavior of a Programmer and Manager and represent these as a new class, Employee. You can define the class Employee as an abstract class, if you think that it’s only a categorization and no real Employee exists in real life—that is, if all Employees are really either Programmers or Managers. That’s the essence of an abstract class: it groups the common properties and behavior of its derived classes, but it prevents itself from being instantiated. Also, an abstract class can force all its derived classes to define their own implementations for a behavior by defining it as an abstract method (a method without a body).
Section 6.6.1 includes an example of usage of abstract classes: how it forces its derived classes to implement the abstract methods.
It isn’t mandatory for an abstract class to define an abstract method. But if an abstract base class defines one or more abstract methods, the class must be marked as abstract and the abstract methods must be implemented in all its concrete derived classes. If a derived class doesn’t implement all the abstract methods defined by its base class, then it also needs to be an abstract class.
For the exam, you need to remember the following important points about implementing inheritance using an abstract base class:
The first Twist in the Tale exercise for this chapter queries you on the relationship between base and derived classes (answer in the appendix).
Modify the code used in the previous example as follows. Which of the options is correct for this modified code?
class Employee { private String name; String address; protected String phoneNumber; public float experience; } class Programmer extends Employee { Programmer (String val) { name = val; } String getName() { return name; } } class Office { public static void main(String args[]) { new Programmer ("Harry").getName(); } }
Following is a list of terms and their corresponding definitions that you should remember; they’re used throughout the chapter, and you’ll come across them while answering questions on inheritance in the OCA Java SE 8 Programmer I exam.
The terms base class, superclass, and parent class are used interchangeably. Similarly, the terms derived class and subclass are also used interchan-geably.
In this section, you learned that an abstract class may define abstract methods. Let’s take it a step further to interfaces. In the next section, we’ll discuss why you need interfaces and how to use them.
18.188.152.136