A para implementation of the Java interface

Is there a preferred method or style for creating a default implementation for interface methods? Suppose I had a widely used interface, where in 90% of cases the functionality that I wanted was identical.

My first instinct is to create a concrete class with static methods. Then I would delegate functions to static methods when I need the default functionality.

Here is a simple example:

Interface

public interface StuffDoer{ public abstract void doStuff(); } 

Concrete implementation of methods

 public class ConcreteStuffDoer{ public static void doStuff(){ dosomestuff... } } 

Specific implementation using standard features

 public class MyClass implements StuffDoer{ public void doStuff(){ ConcreteSuffDoer.doStuff(); } } 

Is there a better approach here?

EDIT

Having seen several proposed solutions, I think that I should more clearly tell about my intentions. Essentially, I'm trying to work on Java without allowing multiple inheritance. Also, to be clear, I'm not trying to make an expression about whether Java should allow multiple inheritance. I'm just looking for the best way to create a default implementation of a method for classes that implement an interface.

+15
java design design-patterns
Aug 6 '10 at 19:27
source share
10 answers

Here is an approach:

 public interface MyInterface { MyInterface DEFAULT = new MyDefaultImplementation(); public static class MyDefaultImplemenation implements MyInterface { } } 

Of course, MyDefaultImplementation can be private or its own top-level class, depending on what makes sense.

In your implementations, you may have the following:

  public class MyClass implements MyInterface { @Override public int someInterfaceMethod(String param) { return DEFAULT.someInterfaceMethod(param); } } 

This is a bit more self-documenting and ultimately more flexible than the default implementation class, which exists elsewhere but is not referenced by the interface. With this, you can do things such as simply passing the default implementation as a method parameter when necessary (which you cannot do with static methods).

Of course, the above only works if no state is involved.

+22
Aug 09 '10 at 16:45
source share

You can turn an interface into an abstract class and provide a default implementation for the corresponding methods.

Update: I see multiple inheritance closes the interface change to an abstract class ... in this case, I would do the same as you. If the standard implementation of the method (s) is stateless, the best place for them is really in the static utility class. However, if there is a state involved, I would consider the composition of the object, which could even appear in the form of a Decorator .

+16
Aug 6 '10 at 19:29
source share

Now that Java 8 is missing, this template is much nicer:

 public interface StuffDoer{ default void doStuff() { dosomestuff... } } public class MyClass implements StuffDoer { // doStuff automatically defined } 

Lambda attracted all the attention, but this was the most tangible advantage of Java 8 for our company. Our inheritance hierarchies got a lot easier when we no longer needed to have abstract classes in order to have a default implementation.

+7
Nov 17 '14 at 10:39
source share

I follow more or less the pattern that I originally learned from Swing. I have an interface, then I create the class "Base" or "Adapter". For me, the adapter will often have nothing to implement for all interface methods, to allow the developer to write only the methods they need, ignoring the rest. The base will be an abstract class that provides convenient implementations of some interface methods — I hope this is the “most likely” implementation.

For example, I have a SearchFilter interface that, among other things, has an apply(Collection<T>) method. This method will almost always go through the collection and invoke the boolean include(T item) interface method to decide whether to save or filter the item. My SearchFilterBase provides this as an implementation for apply (), and the developer needs to write his own include () logic.

Developers are free, of course, just to implement the entire interface on their own and not to remove from the database, which is an advantage over changing the interface to an abstract class, which forces them to use their single inheritance (this is the problem with java.util.Observable)




In response to comment N8g. You can subclass the base or adapter, but are not required for the subclass - you can implement the interface yourself from scratch. The base or adapter is provided as a convenience by implementing no-op methods, so you do not need to do this or implement convenient general functions in an abstract base class (for example, my SearchFilterBase class). The advantage of this is that turning an interface into an abstract class is that you are not imposing inheritance from your abstract class.

+1
Aug 07 2018-10-10T00: 00Z
source share

I would also use static methods to declare default functions for functions without saving.

For stateful functionality, I would prefer composition over inheritance. With the composition and use of delegates / adapters, you can combine default functionality from many sources.

eg.

 public interface StuffDoer{ void doStuff(); void doOtherStuff(); } public class MyStuffDoer implements StuffDoer{ private final StuffDoer mixin; public MyStuffDoer(StuffDoer mixin){ this.mixin = mixin; } public void doStuff(){ mixin.doStuff(); } public void doOtherStuff(){ mixin.doOtherStuff(); } } public class MyStuffDoer2 implements StuffDoer{ private final StuffDoer mixin1, mixin2; public MyStuffDoer(StuffDoer mixin1, StuffDoer mixin2){ this.mixin1 = mixin1; this.mixin2 = mixin2; } public void doStuff(){ mixin1.doStuff(); } public void doOtherStuff(){ mixin2.doOtherStuff(); } } 

For simple cases, inheritance is also good, but actually it is not very flexible.

Implementing multiple interfaces is also an example where this approach scales better.

 public interface A{ void doStuff(); } public interface B{ void doOtherStuff(); } public class MyStuffDoer implements A, B{ private final A mixin1; private final B mixin2; public MyStuffDoer(A mixin1, B mixin2){ this.mixin1 = mixin1; this.mixin2 = mixin2; } public void doStuff(){ mixin1.doStuff(); } public void doOtherStuff(){ mixin2.doOtherStuff(); } } 

You cannot do this with abstract classes. I used this composite approach for several projects, and it worked pretty well.

+1
Aug 08 '10 at 20:48
source share

Static implementations have two problems:

  • you cannot find them using any static code analysis, for example, listing all developers, since the static method does not implement the interface, so you are forced to mention the default implementation in javadoc

  • sometimes it requires some state in the implementation, which cannot be done in a static method

Thus, I prefer to use a specific class that allows both inheritance (if you are not limited to single inheritance) and composition, and call the resulting * Peer class, since it will usually be used together with the implementation of the main class interface. The peer will implement the interface and may also have a link to the main object if it needs to activate events in the name of the main class.

+1
Aug 08 '10 at
source share

In most cases, I move on to something like this:

 public interface Something { public void doSomething(); public static class Static { public static void doSomething(Something self) { // default implementation of doSomething() // the name of the method is often the same // the arguments might differ, so state can be passed } } public static abstract class Abstract implements Something { // the default abstract implementation } public static class Default extends Abstract { // the default implementation public void doSomething() { Static.doSomething(this); } } public static interface Builder extends Provider<Something> { // initializes the object } } 

I usually use inner classes because these classes are really related, but you can also use regular classes.

In addition, you can put the utility class ( Static ) in a separate file if the methods are not limited to the interface.




By the way, the problem with decorators is that they hide other implemented interfaces. In other words, if you have something decorator, then this is false new SomethingDecorator(new ArrayList<Object>()) instanceof List<?> If SomethingDecorator does not implement the list interface. You can work arround using the reflection API and, in particular, using Proxy .

Another good aproach are adapters, as indicated by PersicsB.

+1
Aug 09 '10 at 17:09
source share

Dependency inclusion can be provided by the delegate and indicate a default implementation that can be overridden in unit tests.

For example, the Guice framework supports interface annotation for the default implementation, which can be overridden by explicit binding in unit tests.

 @ImplementedBy( ConcreteStuffDoer.class ) public interface StuffDoer{ void doStuff(); } public class ConcreteStuffDoer implements StuffDoer { public void doStuff(){ ... } } public class MyClass implements StuffDoer{ @Inject StuffDoer m_delegate; public void doStuff(){ m_delegate.doStuff(); } } 

This means that creating a MyClass instance requires a Guice method, not just new .

+1
Aug 12 '10 at 16:18
source share

Composition is superior to multiple inheritance in terms of flexibility. As with the adapter template (see the GOF Book), this allows us to adapt (morphing) classes to different types of behavior depending on the request of callers. See IAdaptable Interface in Eclipse RCP. Basically, using interfaces is similar to using an adapter template built into the Java language directly. But using custom classes is better than implementing multiple interfaces. Adaptable classes are more flexible, but they have some processor overhead: the instanceof operator consumes less CPU than canAdapt (Class clazz). But in modern JVMs, this can be false, as calculating instanceof with interfaces is more complicated than calculating instanceof with inheritance.

0
Aug 09 '10 at
source share

If this is your any function :-) it works as a static one, you do not need to delegate it to everyone, since it does not require "this" - this is a utility function.

You can reconsider whether you really have a huge reason not to combine everything that you consider the default implementation into the first abstract class that implements this interface - you know, adaptation to reality :-)

In addition, you can create secondary, protected virtual methods in an abstract class, which your interface methods will call the one who gives you more control, i.e. the derived class does not have to replace methods, but copy and paste 90% code - it can simply override the method called from the main methods. Gives you a degree of behavioral inheritance.

0
Aug 14 '10 at 23:39
source share



All Articles