Java Abstract Interface

Java abstract interface

Why is it necessary for an interface to be "declared" abstract?

It's not.

public abstract interface Interface {
\___.__/
|
'----> Neither this...

public void interfacing();
public abstract boolean interfacing(boolean really);
\___.__/
|
'----> nor this, are necessary.
}

Interfaces and their methods are implicitly abstract and adding that modifier makes no difference.

Is there other rules that applies with an abstract interface?

No, same rules apply. The method must be implemented by any (concrete) implementing class.

If abstract is obsolete, why is it included in Java? Is there a history for abstract interface?

Interesting question. I dug up the first edition of JLS, and even there it says "This modifier is obsolete and should not be used in new Java programs".

Okay, digging even further... After hitting numerous broken links, I managed to find a copy of the original Oak 0.2 Specification (or "manual"). Quite interesting read I must say, and only 38 pages in total! :-)

Under Section 5, Interfaces, it provides the following example:

public interface Storing {
void freezeDry(Stream s) = 0;
void reconstitute(Stream s) = 0;
}

And in the margin it says

In the future, the " =0" part of declaring methods in interfaces may go away.

Assuming =0 got replaced by the abstract keyword, I suspect that abstract was at some point mandatory for interface methods!


Related article: Java: Abstract interfaces and abstract interface methods

what is a abstract method on a interface in java

abstract is redundant in this case. All methods defined on an interface are public and abstract by definition.

Excerpt Java Language Specification section 9.4

Every method declaration in the body of an interface is implicitly
abstract, so its body is always represented by a semicolon, not a
block.

Every method declaration in the body of an interface is implicitly
public.

Why declare an interface as abstract?

Where did you come across the chunk of code you have posted, any old java code base ?

This is what the JLS has to say :

9.1.1.1 abstract Interfaces:
Every interface is implicitly abstract. This modifier is obsolete and should not
be used in new programs.

9.4 Abstract Method Declarations:
For compatibility with older versions of the Java platform, it is permitted but
discouraged, as a matter of style, to redundantly specify the abstract modifier
for methods declared in interfaces.

Creating an interface with an abstract method

JLS says this:

9.4 Abstract Method Declarations:

For compatibility with older versions of the Java platform, it is
permitted but discouraged, as a matter of style, to redundantly
specify the abstract modifier for methods declared in interfaces.

You also don't need to specify public for interface methods.

See the documentation for Defining an Interface:

All abstract, default, and static methods in an interface are
implicitly public, so you can omit the public modifier.

public interface Payable
{
double getPaymentAmount();
}

You'll need an implementation of the interface to actually implement the logic. For example something like this:

public class PayableImpl implements Payable 
{
double getPaymentAmount()
{
// actual implementation that returns the payment amount
}
}

When to use interface vs abstract class after Java 8

default methods on interface

Apparently you are referring to the feature of “default methods” implementing behavior in an interface.

You should understand that the feature was added as a way around this dilemma: How to retroactively add features leveraging streams and lambda on existing interfaces without breaking existing classes that implement those interfaces?

Many new methods were added to those interfaces such as in the Java Collections Framework. Adding methods to an existing interface would automatically break all classes implementing the interface that are lacking the newly-required methods. Being able to provide a fallback, to give an implementation where one is now required but not yet existing, would resolve the dilemma. Thus « default methods » were born.

To quote from the Oracle tutorial linked above:

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

To quote this Answer by Brian Goetz, Java Language Architect at Oracle:

The proximate reason for adding default methods to interfaces was to support interface evolution

So this feature of adding default behavior to an interface was not meant to be a new mainstream feature in and of itself. The intent of default was not to replace abstract.

Indeed, some experienced Java experts have recommended against making a habit of writing default methods on an interface. They recommend pretty much ignoring that feature of the Java language. Continue to think of interfaces as simply defining a contract, and abstract classes as providing partial implementations meant to be completed in a subclass.

You are certainly free to write your own default methods on your interfaces. And certainly you should do so if you are in a similar situation of having published an interface that others may have implemented, and now you want to add methods. But unnecessarily adding default methods is likely to confuse other programmers who expect partial implementations on an abstract class rather than an interface.

Four situations calling for default method on an interface

In that same post linked above, Brian Goetz suggests three other cases beyond interface evolution where default methods on an interface may be appropriate. Here is a quick mention; see his post for details.

  • Optional methods - The default method throws an UnsupportedOperationException because we expect implementations of this interface to more often not want to implement this method.
  • Convenience methods
  • Combinators

Start with interface, move to abstract class for shared code

As for choosing between an interface and abstract class:

  • Generally start with an interface. Or several interfaces if you want various implementing classes to mix various contracts (see mixin).
    • Think twice before adding a default method. Consider if your situation meets one of the four cases recommended by Brian Goetz as discussed above.
  • If you come to realize that you have duplicated code across multiple classes, then consider centralizing that shared code to an abstract class to be used across subclasses.
    • Alternatively, use composition rather than inheritance (discussed below).

For example, you might have a class for domestic ShippingLabelUS as well as ShippingLabelCanada and ShippingLabelOverseas. All three need to convert between imperial pounds and metric kilograms. You find yourself copying that code between the classes. At this point you might consider having all three classes extend from abstract class ShippingLabel where a single copy of the weight conversion methods live.

While designing your API keep in mind that Java, like most OOP languages, has single-inheritance. So your subclasses are limited to extending only one class. To be a bit more specific about the single-versus-multiple inheritance, I will quote Brian Goetz from this PDF of a slide deck:

[regarding default methods on an interface]

Wait,is this multiple inheritance in Java?

• Java always had multiple inheritance of types

• This adds multiple inheritance of behavior

• But not of state, where most of the trouble comes from

Composition over inheritance

An alternative to using an abstract class for shared behavior is creating a separate class for specific behavior, then adding an object of that separate class to be kept as a member field on the larger class. Wise programmers often share this pearl of wisdom: Prefer composition over inheritance.

Regarding the shipping label example above, you could create a WeightConverter class, an object of which would be a member of each of the three label classes. In this arrangement, no need for the abstract class.

What happens when an abstract class implements an interface in Java

You can imagine an abstract class as an unfinished class. It's like a template for actual real classes. Interfaces are mainly used to describe properties, like CanWalk, IsCloseable, HasAName and so on.

There is no big difference between both concepts from the language perspective, other than that you can only extend from one class but are allowed to implement multiple interfaces.

In the end of the inheritance chain you will always have non-abstract concrete classes. Which is obvious, you can't use unfinished classes in the end, you need to finish them. That's why

Animal animal = new Animal();

does not work if Animal is abstract. We need to create instances of finished classes, like a Dog who extends from Animal.


And at that point, where you have a finished (non-abstract) class, all abstract methods need to be implemented. It doesn't matter from where those methods come from, abstract classes or interfaces, they need to be implemented.

So if you have an abstract class and implement an interface with it, you have two options for the interface methods. You either

  • implement them in the abstract class or
  • you leave them abstract, but then some of your more concrete children need to implement it.

Example

Let's suppose we have an interface like

public interface CanMakeNoise {
void makeNoise();
}

and the abstract class

public abstract class Animal implements CanMakeNoise {
public abstract void jump();

...
}

together with a concrete extending class

public class Dog extends Animal {
...
}

Since Dog is not abstract, all methods need to be implemented. That is, we need implementations for jump and makeNoise. For the makeNoise method we have two options, either Animal implements it or it leaves it abstract, then Dog needs to implement it:

// Variant 1
public abstract class Animal implements CanMakeNoise {
public abstract void jump();

@Override
public void makeNoise() {
System.out.println("hello, what's up");
}
}

or

// Variant 2
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
}

public class Dog extends Animal {
@Override
public void makeNoise() {
System.out.println("Wuff wuff");
}
}

And of course Dog needs to implement jump:

public class Dog extends Animal {
@Override
public void jump() {
System.out.println("Boing");
}

...
}

In this case it's probably better to leave the implementation of makeNoise up to more concrete classes since Animal has no clue how a specific animal will sound like.

Extending the example, if you have even more concrete classes like a Chihuahua extends Dog, you could implement the makeNoise in Dog since all dogs do "Wuff, wuff".

Abstract class and interface together?

It's perfectly normal to use these two together. Consider for instance AbstractList (implementing List) and AbstractMap (implementing Map) in the JDK.

My knee-jerk reaction would have been to have the abstract class implement the interface and then have the concrete classes derive from it:

abstract class Base implements TheInterface {
/* ...shared methods... */
}

class Concrete1 extends Base { }

class Concrete1 extends Base { }

But your question raising the other possibility made me think, and I can't see much of an argument against doing it that way:

abstract class Base {
/* ...shared methods... */
}

class Concrete1 extends Base implements TheInterface { }

class Concrete1 extends Base implements TheInterface { }

Further, I can see an argument for doing it that way, specifically that it removes the coupling between the abstract class and the interface. If you have another class that needs the functionality Base provides but doesn't need to implement the interface, you have the flexibility to do that.

There's also a third option: Composition. You could not have an abstract class at all, but rather have the multiple concrete classes that implement the interface use a common helper class in their implementation:

class Helper {
/* ...shared methods... */
}

class Concrete1 implements TheInterface {
/* ...uses instance of Helper */
}

class Concrete1 implements TheInterface {
/* ...uses instance of Helper */
}

This has that same flexibility, in another form.



Related Topics



Leave a reply



Submit