Find something

Monday, 8 December 2014

The Magic of Java 8: Multiple Inheritance

For ages, Java programmers have been confined (to some extent) regarding inheritance issues. The problem is that Java™ is was unable to support Multiple Inheritance. With the advent of Java 8 in March, this year, this problem has been solved.

Let us assume a problem to illustrate our problem. Say, there are two classes: Singer and Dancer. Now, we have plenty of different types singers and dancers. We have ClassicalSingers, FolkSingers, Rappers, etc. For dancers, we also have several other distinctions. This is fairly easy to represent in Java, using a little bit of Inheritance:
class Singer {
    // an example method.
    public void sing() {
        System.out.println("Do Re Me ... ");
    }
}
abstract class Dancer {
    // an unimplimineted method.
    public abstract void dance();
}
class ClassicalSinger extends Singer {
    @Override   // i.e. it overrides the default method.
    public void sing() {
        System.out.println("Saa Re Gaa ... ");
    }
}
class WesternSinger extends Singer {
    // no need for any method, as sing() is inherited.
}
class HipHopDancer extends Dancer{
    @Override
    public void dance() {
        System.out.println("Doing the windmill, handstand ... ");
    }
}
    
Well, that was pretty good, right? Let me tell you abstract methods must either be implemented by a subclass, or the subclasss must be abstract as well. But how about Michael Jackson? He was a Singer as well as a Dancer. What do we do now?
Well, the solution is simple, use interfaces instead of classes. Interfaces are very similar to classes. Here's how to do it:
interface Singer {
    public void sing(); // automatically abstract
}
interface Dancer {
    public void dance();
}
class ClassicalSinger implements Singer {
    @Override
    public void sing() {
        System.out.println("Saa Re Gaa ... ");
    }
}
class WesternSinger implements Singer {
    @Override
    public void sing() {    // needs to be implemented
        System.out.println("Do Re Me ... ");
    }
}
class HipHopDancer implements Dancer{
    @Override
    public void dance() {
        System.out.println("Doing the windmill, handstand ... ");
    }
}
The keyword changes here from extends to implements. Another fact is that all methods defined in an interface are automatically abstract, they need to be implemented in every class. And for Michael Jackson (let's say he is a SingerDancer:
class SingerDancer implements Singer, Dancer {
    @Override
    public void sing() {    // needs to be implemented
        System.out.println("Yeah yeah...");
    }
    @Override
    public void dance() {
        System.out.println("Doing the moonwalk ... ");
    }
}
There! Now he is a singer as well as a dancer. But I know you are not impressed and want some methods to be inherited, so that they can be reused. This became possible with Java 8, which gave another use to the default keyword: To create Default Methods. These are methods that can be actually implemented in an interface. Let's add two more methods to Singer and Dancer, respectively:
interface Singer {
    public void sing(); // automatically abstract
    default public void clearThroat() {
        System.out.println("Hem hem ...");
    }
}
interface Dancer {
    public void dance();
    default public void warmUp() {
        System.out.println("... (stretching) Five Six Seven Eight ...");
    }
}
Now our SingerDancer has inherited clearThroat() as well as warmUp() without explicitly defining them. To test them, do this:
public class Main2 {
    public static void main(String[] args) {
        SingerDancer michaelJackson = new SingerDancer();
        michaelJackson.warmUp();
        michaelJackson.clearThroat();
        michaelJackson.sing();
        michaelJackson.dance();
    }
}
and you get this:
... (stretching) Five Six Seven Eight ...
Hem hem ...
Yeah yeah...
Doing the moonwalk ... 
That's it for today folks. Hope it was interesting. Have a good day.

Most Viewed