In Java there is no concept of multiple-inheritance, but with the help of interface we can achieve multiple-inheritance. An interface is a named collection of definition. (without implementation)
An interface in Java is a special kind of class. Like classes, interface contains methods and members; unlike classes, in interface all members are final and all methods are abstract.
//interface definition
//we use interface keyword to declare interface
interface <interface_name>{
variable declaration; //
method declaration; //does not implement them, are always public and abstract.
}
//class which implements interface
public class <class_name> implements <interface_name>{
//the methods declared my interface class should be implemented by the class which implement it.
}
- We cannot instantiate an interface in java that means we cannot create an object of the interface class.
- A class implementing an interface must provide an implementation for all it’s methods unless it’s an abstract class.
- By default, any attribute of the interface is public, static, and final. So, there is no need to provide access modifier to the attribute but if it complies does not complain about it either.
- By default methods are implicitly abstract and public, it makes total sense because the methods don’t have a body and so subclasses can provide the method implementation.
- Static methods cannot be declared in the interfaces – these methods are never abstract and do not express the behavior of the object
Java Types Implementing Interface
There are primarily 5 java types that can implement interfaces that are listed below which we are going to explore over later to depth as follows:
- Java Class
- Java Abstract Class
- Java Nested Class
- Java Enum
- Java Dynamic Proxy
Type 1: Java Class
When a class implements an interface, it is essentially signing a contract. Either the class must implement all the methods declared in the interface and its super interfaces, or the class must be declared abstract.
To declare a class that implements an interface, include an implements keyword in the class declaration. Your class can implement more than one interface, so the implements keyword is followed by a comma-separated list of the interfaces implemented by the class.
Example
Java
// Java Program illustrating Java Class implementing // Interfaces // Importing I/O classes import java.io.*; interface Animal { // final public static int x = 4; // public, static and final int x = 4 ; // Public and abstract void sound(); } // Class implementing interface class Chicks implements Animal { // Implementing the abstract method public void sound() { System.out.println( "cheep" ); } // Main driver method public static void main(String[] args) { Chicks c = new Chicks(); c.sound(); System.out.println( "The value of x = " + x); } } |
cheep The value of x = 4
Type 2: Java Abstract Class
Interface and abstract classes are similar in many ways, but an abstract class allows single inheritance whereas interface allows multiple inheritances. If a class includes an interface but does not fully implement the methods required by the interface, then the class must be declared an abstract class.
When we implement an interface to an abstract class, its means that the abstract class inherited all the methods of the interface. It is not necessary to implement all the methods in an abstract class, however, it comes to abstract class (by inheritance too), so the abstract class can leave some of the methods in the interface without implementation here. But, when this abstract class will be inherited by some class, they must have to implement all those unimplemented methods there in the abstract class.
Example
Java
// Java Program illustrating Java Abstract Class // implementing Interfaces // Importing I/O classes import java.io.*; interface Animal { public void sound(); public void breed(); } abstract class Cat implements Animal { // Note: It is not necessary to implement // all methods of interface class public void sound() { System.out.println( "meow" ); } } public class Cat1 extends Cat { public void breed() { System.out.println( "Ragdoll" ); } } class Main { public static void main(String[] args) { Cat1 c = new Cat1(); c.breed(); c.sound(); } } |
Ragdoll meow
Type 3: Java Nested Class
Java has the ability to nest a class inside an interface. The nested class is implicitly public and static. Nesting class inside interface can be useful, especially when there is a relationship between the enclosing interface and the enclosed class. Nesting class inside interface can improve the source code’s readability. The class and interface with the same name, nesting can also help you avoid a name conflict between the two.
Example
Java
// Java Program illustrating Java Nested Classes // implementing Interfaces // Importing I/O classes import java.io.*; interface Animal { // Nested class public class Type { public static void animal() { System.out.println( "The animal is cat" ); } } public void breed(); public void sound(); } public class Cat implements Animal { // Method 1 public void breed() { System.out.println( "Munchkin" ); } // Method 2 public void sound() { System.out.println( "Meow" ); } } // Main class class MainClass { public static void main(String args[]) { Cat c = new Cat(); // Calling the nested class Animal.Type.animal(); c.breed(); c.sound(); } } |
The animal is cat Munchkin Meow
Type 4: Java Enum
Enum can implement any interface in Java. Since enum is a type, similar to any other class and interface, it can implement any interface in java. This gives a lot of flexibility in some cases to use Enum to implement some other behavior.
Example
Java
// Java Program illustrating Java Enum class // implementing Interfaces // Importing I/O classes import java.io.*; // interface class interface Cat { public void breed(); } // Class 1 // Enum class enum Breed implements Cat { Siamese, Persian, Bengal, Burmese; public void breed() { System.out.print( "The breed is " + this ); } } // Class 2 // Main class public class MainClass { // main driver method public static void main(String args[]) { Breed.Persian.breed(); } } |
The breed is Persian
Type 5: Java Dynamic Proxy
A proxy calls the object method indirectly through the proxy object. java.lang.reflect API provides a class as Proxy and an interface as InvocationHandler. Together these two API creates a dynamic proxy class. Proxy class creates the dynamic proxy class on the basis of given parameters. InvocationHandler invokes the methods of dynamic proxy class.
Example
Java
// Java Program illustrating Java Dynamic Proxy Class // implementing Interfaces package javaInterface; // Importing I/O classes import java.io.*; // Interface interface Animal { public void breed(); public void sound(); } // Class 1 // Class implementing interface class Cat implements Animal { public void breed() { System.out.println( "Ragdoll" ); } public void sound() { System.out.println( "meow" ); } } // Class 2 // InvocationHandler that simply passes every method call // through to an instance: import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; class LoggingHandler implements InvocationHandler { private final Object target; private Map<String, Integer> calls = new HashMap<>(); public LoggingHandler(Object target) { this .target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if (name.contains( "toString" )) { return calls.toString(); } calls.merge(name, 1 , Integer::sum); return method.invoke(target, args); } } // Class 3 // create a proxy using this invocation handler, we use the // newProxyInstance // static utility method on the java.reflection.Proxy class: import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; class MainClass { @SuppressWarnings ( "unchecked" ) public static <T> T withLogging(T target, Class<T> itf) { return (T)Proxy.newProxyInstance( itf.getClassLoader(), new Class<?>[] { itf }, new LoggingHandler(target)); } public static void main(String args[]) { Cat c = new Cat(); Animal logged = withLogging(c, Animal. class ); logged.breed(); logged.sound(); System.out.println(logged); } } |
Output:
Ragdoll meow {sound=1, breed=1}