views:

226

answers:

2

Just as a counterpoint to this question: what is an interface in Java?

+2  A: 

An interface is a special form of an abstract class which does not implement any methods. In Java, you create an interface like this:

interface Interface
{
    void interfaceMethod();
}

Since the interface can't implement any methods, it's implied that the entire thing, including all the methods, are both public and abstract (abstract in Java terms means "not implemented by this class"). So the interface above is identical to the interface below:

public interface Interface
{
    abstract public void interfaceMethod();
}

To use this interface, you simply need to implement the interface. Many classes can implement an interface, and a class can implement many interfaces:

interface InterfaceA
{
     void interfaceMethodA();
}

interface InterfaceB
{
    void interfaceMethodB();
}

public class ImplementingClassA
    implements InterfaceA, InterfaceB
{
    public void interfaceMethodA()
    {
        System.out.println("interfaceA, interfaceMethodA, implementation A");
    }

    public void interfaceMethodB()
    {
        System.out.println("interfaceB, interfaceMethodB, implementation A");
    }
}

public class ImplementingClassB
    implements InterfaceA, InterfaceB
{
    public void interfaceMethodA()
    {
         System.out.println("interfaceA, interfaceMethodA, implementation B");
    }

    public void interfaceMethodB()
    {
        System.out.println("interfaceB, interfaceMethodB, implementation B");
    }
}

Now if you wanted you could write a method like this:

public void testInterfaces()
{
    ImplementingClassA u = new ImplementingClassA();
    ImplementingClassB v = new ImplementingClassB();
    InterfaceA w = new ImplementingClassA();
    InterfaceA x = new ImplementingClassB();
    InterfaceB y = new ImplementingClassA();
    InterfaceB z = new ImplementingClassB();

    u.interfaceMethodA();
    // prints "interfaceA, interfaceMethodA, implementation A"
    u.interfaceMethodB();
    // prints "interfaceB, interfaceMethodB, implementation A"
    v.interfaceMethodA();
    // prints "interfaceA, interfaceMethodA, implementation B"
    v.interfaceMethodB();
    // prints "interfaceB, interfaceMethodB, implementation B"
    w.interfaceMethodA();
    // prints "interfaceA, interfaceMethodA, implementation A"
    x.interfaceMethodA();
    // prints "interfaceA, interfaceMethodA, implementation B"
    y.interfaceMethodB();
    // prints "interfaceB, interfaceMethodB, implementation A"
    z.interfaceMethodB();
    // prints "interfaceB, interfaceMethodB, implementation B"
}

However, you could never do the following:

public void testInterfaces()
{
    InterfaceA y = new ImplementingClassA();
    InterfaceB z = new ImplementingClassB();

    y.interfaceMethodB(); // ERROR!
    z.interfaceMethodA(); // ERROR!
}

The reason you can't do this is that y is of type interfaceA, and there is no interfaceMethodB() in interfaceA. Likewise, z is of type interfaceB and there is no interfaceMethodA() in interfaceB.

I mentioned earlier that interfaces are just a special form of an abstract class. To illustrate that point, look at the following code.

interface Interface
{
    void abstractMethod();
}

abstract public class AbstractClass
{
    abstract public void abstractMethod();
}

You would inherit from these classes almost exactly the same way:

public class InheritsFromInterface
    implements Interface
{
    public void abstractMethod() { System.out.println("abstractMethod()"); }
}

public class InteritsFromAbstractClass
    extends AbstractClass
{
    public void abstractMethod() { System.out.println("abstractMethod()"); }
}

In fact, you could even change the interface and the abstract class like this:

interface Interface
{
    void abstractMethod();
}

abstract public class AbstractClass
    implements Interface
{
    abstract public void abstractMethod();
}

public class InheritsFromInterfaceAndAbstractClass
    extends AbstractClass implements Interface
{
    public void abstractMethod() { System.out.println("abstractMethod()"); }
}

However, there are two differences between interfaces and abstract classes.

The first difference is that interfaces cannot implement methods.

interface Interface
{
    public void implementedMethod()
    {
        System.out.println("implementedMethod()");
    }
}

The interface above generates a compiler error because it has an implementation for implementedMethod(). If you wanted to implement the method but not be able to instantiate the class, you would have to do it like this:

abstract public class AbstractClass
{
    public void implementedMethod()
    {
        System.out.println("implementedMethod()");
    }
}

That's not much of an abstract class because none of its members are abstract, but it is legal Java.

The other difference between interfaces and abstract classes is that a class can inherit from multiple interfaces, but can only inherit from one abstract class.

abstract public class AbstractClassA { }
abstract public class AbstractClassB { }
public class InheritsFromTwoAbstractClasses
    extends AbstractClassA, AbstractClassB
{ }

The code above generates a compiler error, not because the classes are all empty, but because InheritsFromTwoAbstractClasses is trying to inherit from two abstract classes, which is illegal. The following is perfectly legal.

interface InterfaceA { }
interface InterfaceB { }
public class InheritsFromTwoInterfaces
    implements InterfaceA, InterfaceB
{ }

The first difference between interfaces and abstract classes is the reason for the second difference. Take a look at the following code.

interface InterfaceA
{
    void method();
}

interface InterfaceB
{
    void method();
}

public class InheritsFromTwoInterfaces
    implements InterfaceA, InterfaceB
{
    void method() { System.out.println("method()"); }
}

There's no problem with the code above because InterfaceA and InterfaceB don't have anything to hide. It's easy to tell that a call to method will print "method()".

Now look at the following code:

abstract public class AbstractClassA
{
    void method() { System.out.println("Hello"); }
}

abstract public class AbstractClassB
{
    void method() { System.out.println("Goodbye"); }
}

public class InheritsFromTwoAbstractClasses
    extends AbstractClassA, AbstractClassB
{ }

This is exactly the same as our other example, except that because we're allowed to implement methods in abstract classes, we did, and because we don't have to implement already-implemented methods in an inheriting class, we didn't. But you may have noticed, there's a problem. What happens when we call new InheritsFromTwoAbstractClasses().method()? Does it print "Hello" or "Goodbye"? You probably don't know, and neither does the Java compiler. Another language, C++ allowed this kind of inheritance and they resolved these issues in ways that were often very complicated. To avoid this kind of trouble, Java decided to make this "multiple inheritance" illegal.

The downside to Java's solution that the following can't be done:

abstract public class AbstractClassA
{
    void hi() { System.out.println("Hello"); }
}

abstract public class AbstractClassB
{
    void bye() { System.out.println("Goodbye"); }
}

public class InheritsFromTwoAbstractClasses
    extends AbstractClassA, AbstractClassB
{ }

AbstractClassA and AbstractClassB are "mixins" or classes that aren't intended to be instantiated but add functionality to the classes that they are "mixed into" through inheritance. There's obviously no problem figuring out what happens if you call new InheritsFromTwoAbstractClasses().hi() or new InheritsFromTwoAbstractClasses().bye(), but you can't do that because Java doesn't allow it.

(I know this is a long post, so if there are any mistakes in it please let me know and I will correct them.)

Imagist
One small remark, you call your class "InheritsFromTwoInterfaces", but when you use interfaces you are usually not speaking about Inheriting, but Implementing, this because the interface does not contain any logic and/or implementation you can inherit. Therefore it is better to speak about implementation (at least that is they learned me).
Gertjan
@Gertjan You are correct. However, I don't think the distinction between "inherits" and "implements" is all that important, especially considering that in many cases one both inherits and implements an abstract class. I chose to keep the naming scheme to be less confusing.
Imagist
interface is like a pipe through which you can access to different classes of objects in a standardized way. Since in Java you cannot extend more than one class, interface is here to satisfy need for more complex inheritance.
ante.sabo
No, interfaces are not used for inheritance. Interfaces are just "contracts" that define the functions and members an class must have when implementing the interface. Interfaces **cannot** be used to work around the "extend issue" (which does not allow you to extend 2 or more classes). when extending a class the functionality of the class you extend is still accessible (through the extending class), but since an interface has no functionality you cannot use it to ommit the multiple inheritance restriction because members and functions need to be written in the implementing class.
Gertjan
+4  A: 

Here's a more concise answer on Wikipedia.

Adamski
This raises a maintainence issue. Who is going to maintain this link if wikipedia change its url? Would it not be better to loosely couple SO and WikiPedia by copying over the more relevent bits from the article onto SO. Of cource this breaks the DRY principle.
mR_fr0g
@mR_fr0g: I see your point but you could say the same about the hundreds of other links posted on SO. I would hope the URL would be maintained to the extent that if it ever becomes invalid someone either amend my post (after trying to follow the link) or let me know and I'll amend it.
Adamski