An Inner class is the one which is defined inside another class. This technique doesn’t seem appealing in the beginning but becomes interesting once we start diving deep to explore features like
- Connection of inner class with outer class
- Multiple inheritance
- Anonymous class
Connection with outer class
Inner class can access fields and methods of outer class as if they are its own.
In above example, inner class ‘Engine’ can invoke private fields & methods of outer class ‘Car’ like it would access its own members. This is possible because inner class keeps a reference of outer class object which is used to instantiate the inner class object. Like any other class keyword new is used to create object of inner class but there is a difference here – for inner class we need to specify object of outer class dot new keyword, e.g. c.new in this example.
Inner class is second technique to achieve multiple inheritance in Java, first one being interfaces. There are real life problems where logical solution lies in a single class inheriting from multiple classes or abstract classes; this can be achieved by outer class extending one class and multiple inner classes extending different classes or multiple inner classes extending same base class differently. For example,
Anonymous inner class
It is a technique using which an object can be created of a class definition by skipping class name. It can be useful in cases where we need only one object of a class.
In above example, getFuel() method of RacingCar returns an anonymous class object by implementing Fuel interface. Also, note the semi-colon to end the return statement.
Interface in Java is a concept to separate contract (what) from implementation (how).
The keyword interface creates an entity which defines how a class is going to look like with method names, their list & type of arguments and their return type. Interface does not define any method body.
One or more classes can implement the interface to provide the actual method body for all the methods declared in the interface . Since interfaces do not contain any method body, Java does not allow creation of objects of interface. Objects can be created for class that implements the interface.
Similar to inheritance, when defining class for interface we specify name of the interface it is implementing. Here we use the keyword implements to define the class.
A class can implement multiple interfaces by separating Interface names using comma after the implements keyword. An object of such class can be upcasted to any of the interfaces. This is Java’s way of multiple inheritance which is directly not allowed with extends keyword.
We have discussed about classes and interfaces, there is another entity in Java called Abstract Class which falls into same category but is midway between class and interface. Mid-way because we can provide definition of some methods (like classes) and leave some as abstract or as declaration (like interfaces). Java does not allow instantiation of abstract class but allows it to be extended like any other class using extends keyword.
In this example, we have created a class TennisPlayer by inheriting from abstract class Person and implementing interface Player. TennisPlayer gets eat() capability from Person but is forced to define work() capability as mandated in same Person abstract class. Similarly, TennisPlayer is forced to implement play() capability of Player interface. Since playing tennis is the work for a tennis player, we reused play as work.
Benefits of using Interfaces & Abstract classes-
- Re-usability: Using inheritance we can design in a way such that code is reused to its maximum. In above example – common activity of a Human like eat is defined in the abstract class.
- Extensibility – Using interfaces we can design applications that are easily extensible in future. In above example – SoccerPlayer can be added easily by implementing Player and extending Person.
Word of caution: Using Interfaces is somewhat tricky because it makes sense to use them only when we have multiple implementations either currently or in future. If there is no scope of multiple implementation in future then its wiser to avoid interface and use a class directly.