Reputation: 45
I've googled extensively for an answer to this question, but I either do not know what the technical term is, or else it's not possible, so forgive any ignorance on my part, please.
First the code, then the rationale behind why.
package package1;
public interface MyInterface {
public ... method1(...);
public ... method2(...);
public ... method3(...);
public ... method4(...);
public static interface|class DEFAULT extends|implements MyInterface {
public abstract ... method1(...);
public ... method2(...) {
// code
}
public ... method3(...) {
// code
}
public abstract ... method4(...);
}
}
Now normally I would abstract a class to implement MyInterface
, but in this case, I cannot, as Java (understandably) does not support class inheritance from multiple classes (although interfaces can extend multiple other interfaces).
My (ideal) use case would be something along the lines of:
package package3;
import package1.MyInterface;
import package2.SomeBaseClass;
public class MyClass extends SomeBaseClass implements MyInterface.DEFAULT {
// other class code
public ... method1(...) {
// code
}
public ... method4(...) {
// code
}
}
I could probably figure out some workaround, but I want to know if there is an easier/more elegant way to do this, before I spend a ton of time writing code that might end up being outclassed by something I hadn't thought of.
Edit: I should have specified that each of the classes/interfaces are from different packages (the above code has been modified to reflect this distinction). Basically I'm combining the functionality of two packages into a third.
Edit: I've come up with the following, which I believe follow the solutions\comments suggested of accomplishing this by composition.
package MyPackage;
import package1.SomeBaseClass;
import package2.MyInterface;
public class MyClass extends SomeBaseClass {
private .. someVariable;
private MyInterface myInterface = new MyInterface.DEFAULT() {
public ... method1(...) {
// do something with someVariable
}
public ... method4(...) {
// code
}
};
public void doSomethingThatRequiresMyInterface() {
myInterface.method1(...);
}
}
Am I understanding this correctly?
Upvotes: 0
Views: 233
Reputation: 7217
You could use composition, where you would create a class that implements the interface, and provides the default functionality, and then pass an instance of the default implementation to the concrete class. If the concrete class doesn't provide the functionality, call the version implemented by the default instance.
Interface:
public interface Foo {
int method1(int a, String b);
String method2(int a);
String method3(String b);
}
Default Implementation:
public class DefaultFoo implements Foo {
@Override
public int method1(int a, String b) {
return a + b.length();
}
@Override
public String method2(int a) {
return a;
}
@Override
public String method3(String b) {
return b;
}
}
Concrete Implementation:
public class GreenFoo implements Foo {
Foo defaultFoo = new DefaultFoo();
@Override
public int method1(int a, String b) {
return "Green " + a + ", Mean" + b;
}
@Override
public int method2(int a) {
return a*a;
}
@Override
public int method3(Sting b) {
// I don't want to implement this, so I just call the default.
return defaultFoo.method3(b);
}
}
Upvotes: 0
Reputation: 764
If you are using/can use Java 8 'default methods' might be what you are looking for -> http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
However, I don't think you are far off from what you want to achieve with the code listed above.
MyInterface.java
public interface MyInterface {
public ... method1(...);
public ... method2(...);
public ... method3(...);
public ... method4(...);
}
Default.java
public abstract class Default implements MyInterface {
public abstract ... method1(...);
public ... method2(...) {
// code
}
public ... method3(...) {
// code
}
public abstract ... method4(...);
}
SomeBaseClass.java
public abstract class SomeBaseClass extends Default {
public void someNewMethod();
}
MyClass.java
public class MyClass extends SomeBaseClass {
// other class code
@Override
public ... method1(...) {
// code
}
@Override
public ... method4(...) {
// code
}
}
Upvotes: 1
Reputation: 17487
If I understood your requirements well, I think the new default methods (also known as defender methods) that were introduced in Java 8 could help you (tutorial at Oracle).
They allow to define a default behaviour for interface methods, so that classes implementing them don't have to duplicate this default behaviour if it is sufficient.
It was introduced mainly so that the Java developement team could add new methods to API interfaces without breaking existing code implementing these interfaces.
Example :
Interface :
public interface MyInterface {
default void method1(String arg1, Object arg2){
//code...
}
default String method2(){
//code...
}
String method3();
}
Implementation class :
public class MyClass implements MyInterface {
private String field1;
public String method3(){
//code...
}
public void someOtherMethod(){
//code...
}
}
In this case, the implementation class doesn't implement the interface's methods marked as default, so they still can be called and the default implementation will be used. However it still has to implement the method3
that has no default implementatio in the interface.
There are limitations and caveats though, a few of which are listed in this blog article, so be careful.
As an aside : you don't have to specify the "public" accessor for interfaces methods in Java since it is already the default,
Upvotes: 0