Introduction
Today’s lab will be covering the basics of Inheritance.
What is inheritance? Inheritance is when one class gains the attributes of another, including the inherited class’s methods and variables. This allows us to define more complex classes through the use of more general base classes.
So how does this work? Inheritance works by taking existing code and building on top of it by using the keyword extends in the class header.
For example lets say you have a class named Animal, and you wanted to make a class for Birds. Since for the most part Birds and Animals share many of the same base attributes, you could extend the Animal class and add any extra parts needed to the Bird class. Let’s take a look.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Animal {
public String noise;
public int age;
private String name;
public Animal(String noise, int age, String name){
this.noise = noise;
this.age = age;
this.name = name;
}
public String getName() {
return name;
}
public void speak(){
System.out.println("My name is " + name);
System.out.println("I am " + age + " years old");
System.out.println("I say " + noise);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Bird extends Animal {
public double height;
public String color;
public Bird(String noise, int age, String name, double height, String color){
super(noise, age, name);
this.height = height;
this.color = color;
}
public void printBird(){
System.out.printf("Hello! I am %s and I am a %s Bird! %s!", this.getName(), this.color, this.noise);
}
public void speak(){
super.speak();
System.out.println("I am " + color);
System.out.println("I am " + height + " inches tall");
}
}
Some terminology
- A base class, superclass, and parent class all mean the same thing
- the class that is being extended
- A derived class, subclass, and child class also all mean the same thing
- the class that is doing the extending
In the above example the Animal is the class being extended and Bird is the class doing the extending. So in this example we could say:
- Animal is the parent class
- Animal is the superclass
- Animal is the base class
We could also say:
- Bird is the child class of Animal
- Bird is the subclass of Animal
- Bird is the base class of Animal
Inheriting a Class
When using inheritance we will be talking about the ideas of parent classes, also called superclass or baseclass, and child classes, also called derived class or subclass. The parent class is the class being inherited from. In the previous example Animal is the parent class, as it is the class being extended, as seen when Bird extends Animal. The parent class often is capable of being an object on its own. For example, you can have an object of type Animal, without it needing to be a Bird. A Bird however has many of the same traits as an Animal, but it needs a few more specific pieces of information to be usable, such as the height and color, things that are less important to the basic Animal.
The child class is the class that is performing the inheriting, grabbing from an above parent class. This allows the child class the ability to gain certain traits and tools from the parent class without having to copy and paste large chunks of code. In the previous example, Bird needs some of the traits that Animal has, such as name, age, and noise, however rewriting this code is inefficient. Instead of duplicating code, we use the keyword extends as well as the name of the class we want to extend Animal (thus giving us Bird extends Animal) which tells the system to bring anything from Animal that can be inherited, such as public class variables and methods.
Super
The keyword super is used to tell the system that you want to use something from the superclass (parent class). It is used to call methods from the superclass, and to access the superclass constructor. Let’s go over this
In a constructor
When inheriting a class, there is something special to be done inside the constructor. The FIRST LINE inside the subclass’s constructor should always be a call to super constructor. This is because we need to invoke the constructor to set all of the information in the parent, in order to use our child class, so we call the parents constructor to set all of the needed information. If the parent class has a constructor with no parameters your call will look like this super();. But if the parent class has a constructor with parameters, the call will look like this super( parameter list );.
Using a method
When wanting to use a method inside the super class, you can use a call such as super.methodName();. This will call the method in the above super class just like calling any other method. This comes in handy when overriding methods and reusing code. A call to a method using the keyword super specifies that you want to use a method from the super class, not a method from the class you are currently in. This comes in handy when overriding methods.
For example, in the Bird class we can call this.getName() because we have no other getName method, except the one in our parent class. Therefore, the system knows to look in the super class. BUT, in the speak method, we have to use super.speak() because if we had used the keyword this, we would’ve gotten Bird’s speak method, not Animal’s. Because we have methods of the same name, we must specify the one we want, using the keyword super.
How to Access Information from the Superclass
Now that data has been inherited from the parent class, let’s talk about what you have access to and how to access it. When you inherit from a class you inherit all of the information belonging to that class, however you do not always inherit the right to access it. This may sound a little confusing, so let’s go over it.
Here’s what child classes will always get access to: any public or protected variables or methods. After inheriting, public information staying public, but protected information now becomes private. For example, something that was protected in the Animal class is now seen as private in the Bird class after inheritence.
Private variables and methods are a slightly different story. Although the child class inherits the information stored in the private methods and variables, it lacks the ability to interact with or modify the information stored in those variables without the use of a getter or setter. Just remember that the keyword private means that no one outside of the class has access to it, not even a child class. In the Animal/Bird example, Bird gains the ability to freely access and modify the values stored in noise and age, however is only able to interact with name through the getName and setName Methods. This is why getters and setters are so important. Getters and Setters allow for child classes to be able to interact with private inherited information. Without them child classes cannot interact with private data.
Overriding Methods
When you inherit from a class along with it comes all of the methods and variables the superclass had, but what if you want to write a method with the same name as one of the superclass’s methods? Well you can just override it, by writing a new method with the same name in the subclass. When Java is compiling the code it can tell that the subclass is overriding the method from the superclass and will instead only use the subclass’s version of that method. For example in the Animal/Bird example, Bird overrides the speak() method found in Animal. Overriding a method is especially common with methods such as toString() and equals().
Inheriting from a subclass
It is possible to inherit from a subclass, and in fact all basic inheritance does so. All classes regardless of whether the intent of them is to create an object or not inherit from the built in Java Object Class. Object is the base class that provides a multitude of necessary methods needed for all java classes to function including, toString() and equals(otherObject). Multiple levels of inheritance are very common, especially when multiple items may have shared core attributes but have specific needs within their own class. When inheriting from a class that is also inheriting from another class, the new subclass gains all of the information stored within both the superclass and the superclass’s superclass, following the same rules as normal inheritance. We will talk about this more in depth later but for now I always recommend drawing out an inheritance hierarchy. The top being the main class being extended, and those below it are the subclasses which are extending from it.
instanceof
instanceof is a special keyword used for comparing objects, such as in the equals method. Instead of trying and compare two things that are not of the same type, we first use casting and instanceof to see if two things are comparable. So, the equals method takes an argument of type Object. Meaning it can be any type of object, so it is not necessarily the same type as the class calling the equals method. So, we have to use instaceof to check if the variable coming in is a valid type to be compared to. We use instanceof to make sure we can safely type cast our other object without errors. Here is an example equals method, for the Bird class.
First thing this method does is check if the other object is a Bird, if its not a Bird then we can’t compare it to our Bird object. Next we do a simple comparison between some of the class variables of the two objects. This allows you to specify how closely related two objects need to be in order to be equal. For example if you have two Birds with different heights but the same color you could say they are equal. This ability to define your own equals method gives you lots of flexibility.
Now on to the lab!
Here are the lab instructions:
Step 1
You will be completing a class named Employee that will inherit from the class Person.
- Finish the extends statement in the Employee class header
- Write the Employee constructor don’t forget your call to super
- Create two private class variables: an int id, and a double hourlyPay
- Since they are both private variables, write getters and setters for both variables: getId, getHourlyPay, setId, setHourlyPay
Step 2
In the Employee class complete the getRaise method. This method gives a raise to the user, increasing their total hourly pay by 15%. This method also updates the hourly pay class variable you made as well. Finally return the value of the employee’s new hourlyPay.
Step 3
Inside the Employee class complete the method payDay. This method calculates how much the employee earned for the week. First calculate their pay, if the employee worked more than 40 hours, then any hour OVER 40 is worth 1.5 times their normal pay, this is considered overtime pay, otherwise their pay is as normal. Return their total pay for the week.
Example: if I worked 45 hours this week, I would get 5 hours of overtime pay and 40 hours of normal pay.
Step 4
Inside the Employee class let’s override the toString method.
For the toString method you will use the same basic output from Person toString method but add two new lines. Using Person toString method as a starting, the first two lines of our new toString method will look like:
Name: first_name last_name
They are height_feet’ height_inches“
You will now also add the lines:
They make $hourly_pay
They have the employee ID id_number
HINT will a call to super help?
Step 5
Inside the Employee class, we will now override the equals method.
The method will return true if the employees either share the same ID AND their last names are the same Otherwise the two are not the same and the method will return false.
HINT Go back and look at the example given above for instanceof … does that look similar to what we are trying to do?