Interfaces in Java
An interface in Java represents an abstract type; it is a collection of abstract methods and constants. All methods in an interface are abstract, and thus they have only signatures. All variables in an interface are implicitly final and static, and thus they are constants.
A class can implement an interface by defining the methods in the interface. An interface cannot be instantiated. An interface cannot be used to derive a class, and a class cannot be used to derive an interface. An interface can be used to derive another interface (sub-interface).
- A class extends one class.
- A class can implement many interfaces.
- An interface can extented many interfaces.
The following example defines an interface Flyable
. The class Bat
is a subclass of Flyable
.
public class Mammal { public void print() { System.out.println("I am a mammal"); } } public interface Flyable { public void fly(); } public class Bat extends Mammal implements Flyable { public void print() { System.out.println("I am a bat"); } public void fly() { System.out.println("I am a flying bat"); } } ...... Bat b = new Bat(); Flyable f = b; b.print(); b.fly(); f.fly();
Interfaces vs. Abstract Classes
Interfaces and abstract classes are similar. Neither of them can be instantiated. They are both used to build reusable codes.
The difference is that, an abstract class may contain non-abstract methods and non-constant attributes, but an interface contains only abstract methods and constants.
Interfaces with Generic Types
A class or an interface can be defined to manage objects of unknown types. The types will be specified when creating objects.
class Box<T> // T in angle brackets { // manage objects of type T } Box<Widget> b1 = new Box<Widget>; Box<Gadget> b2 = new Box<Gadget>;
As examples, the java.lang.Comparable
and java.util.Iterator
are two interfaces defined in Java library.
- Interface:
public interface Comparable<T>
This interface imposes a total ordering on the objects of each class that implements it. - Methods:
int compareTo(T o)
Compares this object with the specified object for order. Returns a negative integer (less than), zero (equal to), or a positive integer (greater than). - Example: The
String
class implementsComparable<String>
. An example to compare string is as below:"alice".compareTo("bob");
- Interface:
public interface Iterator<E>
Provides a way to loop over a collection of objects. - Methods:
boolean hasNext()
Returns true if the iteration has more elements.E next()
Returns the next element in the iteration. - Example: The
Scanner
class implementsIterator<String>
. An example code is as below.
Scanner sc = new Scanner(...); while (sc.hasNext()) String str = sc.next();
Exampe: Shapes
The following code defines an abstract class Shape
, with subclasses Circle
and Rectangle
. The class Circle
also implements the interface Comparable<Circle>
.
+------------+ +------------+ | Shape | | Comparable | +------------+ +------------+ ^ ^ ^ | | | | ---------------------| | +------------+ +------------+ | Rectangle | | Circle | +------------+ +------------+
public abstract class Shape { protected int x; protected int y; public Shape(int _x, int _y) { x = _x; y = _y; } public void setX(int _x) { x = _x; } public void setY(int _y) { y = _y; } public int getX() { return x; } public int getY() { return y; } public abstract void draw(); public abstract double area(); public abstract double perimeter(); } public class Circle extends Shape implements Comparable<Circle> { private int r; public Circle(int _x, int _y, int _r) { super(_x, _y); r = _r; } public void setRadius(int _r) { r = _r; } public int getRadius() { return r; } public int compareTo(Circle b) { return r - b.r; } public void draw() { System.out.println("Draw a circle of radius " + r + " at (" + x + ", " + y +")"); } public double area() { return r * r * Math.PI; } public double perimeter() { return 2 * r * Math.PI; } } public class Rectangle extends Shape { private int l; private int w; public Rectangle(int _x, int _y, int _l, int _w) { super(_x, _y); l = _l; w = _w; } public void setLength(int _l) { l = _l; } public int getLength() { return l; } public void setWidth(int _w) { w = _w; } public int getWidth() { return w; } public void draw() { System.out.println("Draw a rectangle of length " + l + " and width " + w + " at (" + x + ", " + y +")"); } public double area() { return l * w; } public double perimeter() { return 2 * (l + w); } }