hayden
hayden

Reputation: 2763

How does implementing an interface provide additional functionality?

I understand that an interface is a contract for classes and that if a class implements an interface, then all methods in the interface must be in the class.

Here is an example involving interfaces from this question that confuses me:

public class Contact implements Comparable<Contact> {

    private String name;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }
}

You can then obviously create an ArrayList and sort it by name.

List<Contact> contacts = new ArrayList<Contact>();
Collections.sort(contacts);

But if Contract does not implement Comparable like so:

public class Contact {

    private String name;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }
}

Calling Collections.sort will give a compile time error even though the compareTo method still exists.

Clearly there can be additional functionality provided by implementing interfaces. What is the purpose of interfaces other than for enforcing structure?

Upvotes: 0

Views: 102

Answers (3)

Serge Ballesta
Serge Ballesta

Reputation: 149175

Other answers gave more common usages of interfaces. There are 2 more I am thinking about :

  • simple marker. Serializable contains no method, nor constants, but simply declare that an instance of the class can be successfully serialized to a stream and de-serialized back.
  • JDK proxying. A Proxy can only proxies interfaces. So to proxy a class, you must first export its public methods to one or more interfaces. It is commonly used in Spring framework AOP.

Upvotes: 0

Boris the Spider
Boris the Spider

Reputation: 61198

Because if Contact implements Comparable<Contact> then Contact is a Comparable<Contact>.

Lets take a look at the source code, deep down in ComparableTimSort.countRunAndMakeAscending() there is the line:

if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0)

The pertinent bit is ((Comparable) a[runHi++]) - a[runHi++] is cast to a Comparable and then the compareTo is called on that as a Comparable.

So if Contact implements Comparable<Contact> I can do this:

final Comparable<Contact> contact = new Contact();

If it does not, then I obviously cannot assign the instance to a Comparable type and therefore I have no idea (without resorting to reflection) what methods Contact has.

By implementing Comparable I am telling the compiler that this class is a Comparable and therefore can be treated as one where required. Having to implement the methods is merely a side effect of that.

As to why it's a compile time rather than run time error, you only need to look at the declaration of the method Collections.sort to find out:

public static <T extends Comparable<? super T>> void sort(List<T> list)

So this method is a generic method and it's signature asks for a List<T> where T extends Comparable<? super T>. This is a little tricky to lets break it down.

We need T to extends Comparable<? super T>. So T needs to implements Comparable<? super T> or some subclass of Comparable. ? super T means that it can be Comparable on the type T or any supertype - i.e. if your compareTo can sort Object then it can also sort T (by the Liskov substitution principle).

Upvotes: 1

Le Ish Man
Le Ish Man

Reputation: 461

The above answer is the technical one, but from a design point of view they create a layer of abstraction between the layers of program. This is important when designing a complex system because it reduces dependencies between classes and allows for greater maintainability.

Upvotes: 0

Related Questions