Java Tutorials – Inheritance

Hello, people…! In this post, we will explore the next part of object oriented programming in Java which is Inheritance.

Inheritance

Inheritance is a feature of object oriented programming which allows a class to be created from an existing class. More formally, inheritance is the process by which the new child subclass automatically includes any public or protected primitives, objects or methods defined in the parent class.
Let us see what is means. In Java, we implement inheritance by using the extends keyword at the time of class declaration. Go through the cod snippet below carefully –

class ParentClass {
    int var;
}

class ChildClass extends ParentClass {
    // empty
}

public class InheritanceDemo {

    public static void main(String[] args) {
        ParentClass parent = new ParentClass();
        ChildClass child = new ChildClass();

        System.out.println(parent.var);
        System.out.println(child.var);
    }

}

Important things to note are –

  • ChildClass inherits ParentClass using the keyword extends.
  • When ChildClass inherits the ParentClass, all the public/protected/default methods and variables are automatically available to the ChildClass.

So, when a ChildClass inherits (or extends) a ParentClass it gets a few resources from the ParentClass. Now let us see exactly what get’s inherited and what does not.

What is inherited?

  • public or default variables.
  • public or default methods.
  • abstract methods (remember abstract methods cannot be private).
  • public or default static methods.

What is not inherited?

  • constructors are not inherited.
  • private variables.
  • private methods.
  • private static methods.

this reference

Let’s say you have a class like this –

class Point {
    int x, y, z;

    public Point(int xValue, int yValue, int zValue) {
        x = xValue;
        y = yValue;
        z = zValue;
    }
}

Now, the constructor’s formal parameter names are descriptive, but a little redundant. In some cases, we would want the name of the formal parameter (xValue) to be same as that of the instance variable (x). What would happen if we did this?

class Point {
    int x, y, z;

    public Point(int x, int y, int z) {
        x = x;  // Assignment to itself
        y = y;
        z = z;
    }
}

It is of no use because the x inside the method is the formal parameter but not the instance variable of Point class. This happens because a local variable takes precedence over a global variable. So, how do we reference the instance variables where the formal parameters have the same name? We use this keyword! Take a look at the constructor below –

class Point {
    int x, y, z;

    public Point(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

We use this reference to refer to the instance variables, or, more formally, this reference is used to refer to the current instance. By current instance we imply the instance variables and methods. So, in the above code snippet, the instance variables are initialized to the formal parameters of the constructor.

So now that you know what this reference can you guess the output of the following code snippets?

Code SnippetSnippet Output
class Point {
    int x, y, z;

    public Point(int x, int y, int z) {
        x = x;
        this.y = y;
        z = this.z;
    }
}

class InheritanceDemo {

    public static void main(String[] args) {
        Point p = new Point(10, 20, 30);

        System.out.println(p.x);
        System.out.println(p.y);
        System.out.println(p.z);
    }

}
0
20
0

I hope you got the answer right! Let us look at the three statements in the constructor. The first statement assigns the formal parameter x to itself. The second statement is the right way of initializing, and hence y outputs 20. The third statement assigns the instance variable z (value is 0 currently) to the formal parameter z (value changed from 30 to 0).

super reference

Let’s say we have two classes, Doctor and ExpertDoctor. A Doctor works on a few things only whereas an ExpertDoctor does a little more than what a Doctor can do. The classes may look like –

class Doctor {
    public void work() {
        System.out.println("Check blood pressure");
        System.out.println("Check haemoglobin levels");
        System.out.println("Check glucose levels");
    }
}

class ExpertDoctor extends Doctor {
    public void work() {
        System.out.println("Check blood pressure");
        System.out.println("Check haemoglobin levels");
        System.out.println("Check glucose levels");
        System.out.println("Check liver functioning");
        System.out.println("Check heart functioning");
    }
}

Well, an ExpertDoctor IS A Doctor, so ExpertDoctor inherits Doctor class. But clearly, we are not getting any advantage here. The work() in ExpertDoctor does a little more than work() in Doctor. Wouldn’t it be nice if we could call work() method of Doctor class inside ExpertDoctor class? Then we would have to write only the additional work done by the ExpertDoctor. This can be achieved by using super reference!

class Doctor {
    public void work() {
        System.out.println("Check blood pressure");
        System.out.println("Check haemoglobin levels");
        System.out.println("Check glucose levels");
    }
}

class ExpertDoctor extends Doctor {
    public void work() {
        super.work();
        System.out.println("Check liver functioning");
        System.out.println("Check heart functioning");
    }
}

class InheritanceDemo {

    public static void main(String[] args) {
        ExpertDoctor doc = new ExpertDoctor();

        doc.work();
    }

}

So, we call work() method of Doctor class using super keyword. The output for the above code is –

Check blood pressure
Check haemoglobin levels
Check glucose levels
Check liver functioning
Check heart functioning

super is a keyword used to reference a member defined in the parent class and can be used throughout the child class.

this() constructor call

Can constructors be overloaded? Yes! You can have multiple overloaded versions of a constructor. Example –

class Time {
    int seconds, minutes, hours;
    
    // Contstructor 1
    public Time(int seconds) {
        this.seconds = seconds;
    }
    
    // Constructor 2
    public Time(int seconds, int minutes) {
        this(seconds); // Calls constructor 1
        this.minutes = minutes;
    }
    
    // Constructor 3
    public Time(int seconds, int minutes, int hours) {
        this(seconds, minutes); // Calls constructor 2
        this.hours = hours;
    }
}

In the above example, we several constructors each of which initialize a certain set of instance variables. We can use this() to call a constructor from another constructor.

super() constructor call

Similar to this(), Java has super(). It is used to call the parent class constructor. Example –

class Time {
    int seconds, minutes, hours;
    
    // Constructor 1
    public Time(int seconds) {
        this.seconds = seconds;
    }
    
    // Constructor 2
    public Time(int seconds, int minutes) {
        this(seconds); // Calls constructor 1
        this.minutes = minutes;
    }
    
    // Constructor 3
    public Time(int seconds, int minutes, int hours) {
        this(seconds, minutes); // Calls constructor 2
        this.hours = hours;
    }
}

class Date extends Time {
    int day, month, year;
    
    // Constructor 4
    public Date(int seconds, int minutes, int hours, int day) {
        super(seconds, minutes, hours); // Calls constructor 3
        this.day = day;
    }
    
    public Date(int seconds, int minutes, int hours, int day, int month, int year) {
        this(seconds, minutes, hours, day); // Calls constructor 4
        this.month = month;
        this.year = year;
    }
}

Rules about constructors –

  • The first line of the constructor must be a call to another constructor of the same class, or a call to the constructor of parent class.
  • If you don’t make a constructor call in the first line, Java automatically adds super() to the first line. So, if there’s no constructor in super class that matches to super(), a compilation error occurs.
  • If you don’t want Java to add a super() automatically in the first line, you must write your own constructor call explicitly.

I hope my post gave you a fair understanding of what inheritance is. If you have any doubts, feel free to comment them! Keep practicing! Happy Coding!! 😀

Encapsulation in Java

Hello, people..! Now we are going to look at the most basic and the first major topic in Object Oriented Programming, Encapsulation. For those who don’t know OOP, it is very important that you spend a lot of time trying to understand these concepts. Because once you learn these concepts, it will be exactly the same in any other OOP language (like C++, C#, etc.), only the syntax changes.

Code without Encapsulation

Let us first understand what happens when we don’t follow encapsulation. Let’s say you created the Person class where all the instance variables were public. The code would look like –

class Person {
    public String name;
    public int age;
}

Now, since it was public, somebody used it in this way in his main() method –

public static void main(String[] args) {
    Person p = new Person();

    p.name = "Vamsi Sangam";
    p.age = -1;
}

Okay, so doing that is legal. Neither the compiler nor the runtime complaints anything about it. But we all know that it’s not sane, right? Seriously, some values can’t be negative, like age, or length, or size etc. It’s like we created this class which everybody is using… Which we are happy about… But they can misuse it, or do stuff not meant for that class. So, we don’t have control.

Encapsulation

So how do get control over things? By implementing encapsulation. So, what’s encapsulation really? It is a set of rules, or a protocol, which we must follow to get more control over our data. Now, what are those rules which we must follow? They are –

  1. Keep instance variables private.
  2. Make public accessor methods.

So, let’s look at it one-by-one. Firstly, we must keep the instance variables private. What does that mean? Well, we just have to write “private” in the place of  “public” before we write the data type of our instance variable. That restricts the scope of the instance variable. Now, the instance variable has scope only inside the class. It cannot be accessed by making an object and referencing it. So, if we implement our rule 1 to Person class, it would look like –

class Person {
    private String name;
    private int age;
}

So, if you tried to use this class from another class’ main() method, and try to access those variables, it will give you a compilation error, saying “age has private access in Person”. The code is –

class Person {
    private String name;
    private int age;
}

class TestPerson {
    public static void main(String[] args) {
        Person p = new Person();
        
        p.age = -1;    // error
    }
}

Great! So it looks like things went from bad to worse! We can’t even use those variables. Well, just wait till we implement the second rule. 😉

The second rules ask us to implement accessor methods. As the name suggests, accessor methods, are meant to access the variables which were marked private. These are also called Getter and Setter methods, or sometimes called as Mutator methods. Oracle thought the name “mutate” sounds bad, so we’ll stick to Getter and Setter methods. So, we will implement Getter and Setter methods for our Person class. As the name suggests the Getter method gets the value of the variable and the Setter method sets the variable to some value. The Person class with Getter and Setter methods would look like –

class Person {
    private String name;
    private int age;
    
    // Getter method for variable name
    public String getName() {
        return name;
    }
    
    // Setter method for variable name
    public void setName(String newName) {
        name = newName;
    }
    
    // Getter method for variable age
    public int getAge() {
        return age;
    }
    
    // Setter method for variable age
    public void setAge(int newAge) {
        age = newAge;
    }
}

As you can see that is the format in which we write the getter and setter methods for a variable. What you write inside the function is your wish, but the access modifier “public”, return type, name, or arguments must be in that format. We’ll talk a little about the naming conventions in a few minutes.
Well, you could ask, what’s changed, you could still do the same cruel stuff we did above to your Person class! 😛 Well, look closely, things have changed! You can do the validation stuff in the setter method of ‘age’ variable. To avoid negative values you could do something like –

// Setter method for variable age
public void setAge(int newAge) {
    if (newAge > 0) {
        age = newAge;
    }
}

So, if the input is a valid one you set the ‘age’ variable to the new value, otherwise you ignore. Not just this, you can do any amount of validation you want. You could keep an upper cap of 125 years or anything like that. So you have complete control. Lastly, you would use the encapsulated class like this –

public static void main(String[] args) {
    Person p = new Person();

    p.setName("Vamsi Sangam");
    p.setAge(-1);   // Ignored, so still 0
    p.setAge(19);
}

You can print the values of the variables using the getter methods if you want to. 🙂

JavaBeans Naming Convention

JavaBeans is a standard set by Oracle. It defines a few rules. We will only concern ourselves with the rules regarding the naming of getter and setter methods, commonly known as JavaBeans Naming Convention. It defines the naming conventions we must follow while naming the getter and setter methods. All classes in the Java library follow this convention strictly. JavaBeans calls an instance variables as a “property”. So the rules are –

Rule Example
Properties are private.
private int age;
private boolean happy;
private int numberOfChildren;
Getter methods begin with is if the property is boolean.
public boolean isHappy() {
    return happy;
}
Setter methods begin with set.
public void setAge(int newAge) {
    age = newAge;
}
The method name must have a prefix of set/get/is, followed by the first letter of the property in uppercase, followed by the rest of the property name
public int getNumberOfChildren() {
    return numberOfChildren;
}

Well, that was the convention rules. The first rule isn’t a naming rule, but it’s a part of JavaBeans so I saw it fit to keep it there.

Encapsulation with Mutable Classes

This is a little advanced topic in Encapsulation. Feel free to skip this part if you are new to OOP. But do check this later because it is an important pitfall! Now, mutable classes are those classes whose data can be changed after the object is created. Example, we saw that String objects are not mutable, whereas the objects of StringBuilder are. We must be careful when encapsulating mutable objects. Check out the class below. Do you think it is perfectly encapsulated?

class Person {
    private StringBuilder name;
    
    public Person(StringBuilder name) {
        this.name = name;
    }
    
    // Getter method for variable name
    public StringBuilder getName() {
        return name;
    }
}

So, let’s say we have this class. We don’t have a setter here, but that’s fine, the class is still considered to be encapsulated (for now :P). So, it pretty much looks like we can’t change the value of the variable ‘name’ after we initialize it with a constructor. Now, check this out –

class TestPerson {
    public static void main(String[] args) {
        Person p = new Person(new StringBuilder("Vamsi Sangam"));

        // variable name will hold Vamsi Sangam
        System.out.println(p.getName());
        
        // Storing the return value
        StringBuilder var = p.getName();
        
        // Changing the object returned
        var.append("! Are you confused?");
        
        // Printing the object inside encapsulated class
        System.out.println(p.getName());
        // Prints "Vamsi Sangam! Are you confused?"
    }
}

We’ve somehow managed to change the object held by the encapsulated field which doesn’t even have a getter method! This happens because, the variable name, is a reference to an object. In the getter method, we are returning the same object which name is pointing to. So if you return the reference to that object, you can actually manipulate it as you want, because it’s a mutable object. Changes made to the object returned by the getter method will reflect in the object held by name because they are exactly the same object.

I hope this made sense. Please go through what I said once more if you didn’t understand it. It’s a fairly simple concept. So what do we do in such a situation? We clone that property and return the clone. Cloning means creating a new object of the same data type as the property which has the same content.

So, a proper getter method for name would be –

class Person {
    private StringBuilder name;
    
    public Person(StringBuilder name) {
        this.name = name;
    }
    
    // Getter method for variable name
    public StringBuilder getName() {
        return new StringBuilder(name);
    }
}

class TestPerson {
    public static void main(String[] args) {
        Person p = new Person(new StringBuilder("Vamsi Sangam"));

        // variable name will hold Vamsi Sangam
        System.out.println(p.getName());
        
        // Storing the return value
        StringBuilder var = p.getName();
        
        // Changing the object returned
        var.append("! Are you confused?");
        
        // Printing the object inside encapsulated class
        System.out.println(p.getName());
        // Prints "Vamsi Sangam"
    }
}

All this nuisance is because the property is of a mutable class. If it were something like a String, we wouldn’t have this problem. Because even if two references point to the same object, we cannot change the content of that object they are pointing to.

So, that was Encapsulation! It is a matter of 2 simple rules. Easy! Isn’t it..?! Keep practicing… Happy Coding..!! 😀