Java Interfaces
Java Interfaces
Java includes a concept called interfaces. A Java interface is a bit like a class, except you can only declare methods and variables in the interface. You cannot actually implement the methods. Interfaces are a way to achieve polymorphism in Java. I will get back to this later in this text.
Java Interface Example
Here is a simple Java interface example:
public interface MyInterface { public String hello = "Hello"; public void sayHello(); }
As you can see, an interface is declared using the Java keyword
interface
. Just like with classes, an interface can be declared public or package scope (no access modifier).
The interface contains one variable and one method. The variable can be accessed directly from the interface, like this:
System.out.println(MyInterface.hello);
The method, however, needs to be implemented by some class, before you can access it. The next section will explain how that is done.
Implementing an Interface
Before you can really use an interface, you must implement that interface in some class. Here is a class that implements the
MyInterface
interface shown above:public class MyInterfaceImpl implements MyInterface { public void sayHello() { System.out.println(MyInterface.hello); } }
Notice the the
implements MyInterface
part of the above class declaration. This signals to the Java compiler that the MyInterfaceImpl
class implements the MyInterface
interface.
A class that implements an interface must implement all the methods declared in the interface. The methods must have the exact same signature (name + parameters) as declared in the interface. The class does not need to implement (declare) the variables of an interface. Only the methods.
Interface Instances
Once a class implements an interface you can use an instance of that class as an instance of that interface. Here is an example:
MyInterface myInterface = new MyInterfaceImpl(); myInterface.sayHello();
Notice how the variable is declared to be of the interface type
MyInterface
while the object created is of type MyInterfaceImpl
. This is possible because the class MyInterfaceImpl
implements theMyInterface
interface. You can then reference instances of the MyInterfaceImpl
class as instances of the MyInterface
interface.
You cannot create instances of an interface by itself. You must always create an instance of some class that implements the interface, and reference that instance as an instance of the interface.
Implementing Multiple Interfaces
A class can implement multiple interfaces. In that case the class must implement all the methods declared in all the interfaces implemented. Here is an example:
public class MyInterfaceImpl implements MyInterface, MyOtherInterface { public void sayHello() { System.out.println("Hello"); } public void sayGoodbye() { System.out.println("Goodbye"); } }
This class implements two interfaces called
MyInterface
and MyOtherInterface
. You list the names of the interfaces to implement after the implements
keyword, separated by a comma.
If the interfaces are not located in the same packages as the implementing class, you will also need to import the interface. Interfaces are imported just like classes. For instance:
import com.jenkov.package1.MyInterface; import com.jenkov.package2.MyOtherInterface; public class MyInterfaceImpl implements MyInterface, MyOtherInterface { ... }
Here are the two interfaces implemented by the class above:
public interface MyInterface { public void sayHello(); }
public interface MyOtherInterface { public void sayGoodbye(); }
As you can see, each interface containe one method. These methods are implemented by the class
MyInterfaceImpl
.Overlapping Method Signatures
If a class implements multiple interfaces, there is a risk that some of these interfaces may contain methods with the same signature (name + parameters). Since a class can only implement at method with a given signature once, this could potentially lead to some problems.
The Java specification does not give any solution to this problem. It is up to you to decide what to do in that situation.
Interface Variables
An interface may contain variables and constants. However, often it does not makes sense to put variables in an interface. In some cases it may make sense to define constants in an interface. Especially if those constants are to be used by the classes implementing the interface, e.g. in calculations, or as parameters to some of the methods in the interface. However, my advice to you is to avoid putting variables in interfaces if you can.
All variables in an interface are public, even if you leave out the
public
keyword in the variable declaration.Interface Methods
An interface can contain one or more method declarations. As mentioned earlier, the interface cannot specify any implementation for these methods. It is up to the implementing classes to specify an implementation.
All methods in an interface are public, even if you leave out the
public
keyword in the method declaration.Interfaces and Inheritance
It is possible for an interface to inherit from another interface, just like classes can inherit from other classes. You specify inheritance using the
extends
keyword. Here is a simple example:public interface MySuperInterface { public void saiHello(); }
public interface MySubInterface extends MySuperInterface { public void sayGoodbye(); }
The interface
MySubInterface
extends the interface MySuperInterface
. That means, that theMySubInterface
inherits all field and methods from MySuperInterface
. That then means, that if a class implements MySubInterface
, that class has to implement all methods defined in bothMySubInterface
and MySuperInterface
.
It is possible to define methods in a subinterface with the same signature (name + parameters) as methods defined in a superinterface, should you find that desirable in your design, somehow.
Unlike classes, interfaces can actually inherit from multiple superinterfaces. You specify that by listing the names of all interfaces to inherit from, separated by comma. A class implementing an interface which inherits from multiple interfaces must implement all methods from the interface and its superinterfaces.
Here is an example of an interface that inherits from multiple interfaces:
public interface MySubInterface extends SuperInterface1, SuperInterface2 { public void sayItAll(); }
As when implementing multiple interfaces, there are no rules for how you handle the situation when multiple interfaces have methods with the same signature (name + parameters).
Interfaces and Polymorphism
Interfaces are a way to achieve polymorphism in Java. Polymorphism is a concept that takes some practice and thought to master. Basically, polymorphism means that an instance of an class (an object) can be used as if it were of different types. Here, a type means either a class or an interface.
Look at this simple class diagram:
Two parallel class hierarchies used in the same application. |
The classes above are all parts of a model representing different types of vehicles and drivers, with fields and methods. That is the responsibility of these classes - to model these entities from real life.
Now imagine you needed to be able to store these objects in a database, and also serialize them to XML, JSON, or other formats. You want that implemented using a single method for each operation, available on each
Car
, Truck
or Vehicle
object. A store()
method, a serializeToXML()
method and aserializeToJSON()
method.
Please forget for a while, that implementing this functionality as methods directly on the objects may lead to a messy class hierarchy. Just imagine that this is how you want the operations implemented.
Where in the above diagram would you put these three methods, so they are accessible on all classes?
One way to solve this problem would be to create a common superclass for the
Vehicle
and Driver
class, which has the storage and serialization methods. However, this would result in a conceptual mess. The class hierarchy would no longer model vehicles and drivers, but also be tied to the storage and serialization mechanisms used in your application.
A better solution would be to create some interfaces with the storage and serialization methods on, and let the classes implement these interfaces. Here are examples of such interfaces:
public interface Storable { public void store(); }
public interface Serializable { public void serializeToXML(Writer writer); public void serializeToJSON(Writer writer); }
When each class implements these two interfaces and their methods, you can always access the methods of these interfaces by casting the objects to instances of the interface types. Here is an example:
Car car = new Car(); Storable storable = (Storable) car; storable.store(); Serializable serializable = (Serializable) car; serializable.serializeToXML (new FileWriter("car.xml")); serializable.serializeToJSON(new FileWriter("car.json"));
As you can probably imagine by now, interfaces provide a cleaner way of implementing cross cutting functionality in classes than inheritance.
0 comments: