Can the Java interface in another package be reorganized from my code?

I use the open source API in my Java project and reference its interfaces. One interface ( Foo ) is widely used both in the API and in projects that use it. For my project, I would like to use an interface that provides only a subset of the methods that Foo does so that Foo inherits methods from my new interface ( Bar ). I don’t want to change the Foo interface at all; rather, I would like to be able to write classes that implement Bar , and then manipulate them along with classes that implement Foo , as if they were all Bar .

Since the API is in another package, is there a way to do this so that Bar superclass (interface) of all Foo ?

+4
source share
4 answers

You will probably need to use Aspect for this to happen. Looks like AspectJ has @DeclareParents that can do what you want.

+2
source

I would like to write classes that implement Bar, and then manipulate them together with classes that implement Foo, as if they were an entire bar.

You can create an abstract panel that implements Foo. You will go around the methods shared by the two and implement methods that Bar does not use, so they throw an exception, such as UnsupportedOperationException .

But you cannot manipulate Foo as if it were Bar; it's the other way around. You cannot satisfy the Liskov Substitution Principle, as you suggest.

+3
source

You can use the "Adapter Template" to do the following:

 public class FooAdapter implements Bar { private Foo wrapped; public FooAdapter(Foo foo) { wrapped = foo; } public void op1() { foo.op1(); } public string op2(int param) { return foo.op2(param); } } 
+2
source

Since Java has nominal typing, so org.theirs.Foo nothing to do with org.yours.Foo , even if they have exact exact method signatures, I don’t think it can be done with inheritance in Java. Even with generics, AFAIK cannot say: "This method accepts an instance of Bar<T extends Foo OR Bar> ".

Instead, I think you want to use the adapter interface for the Foo library with your own (that is, a FooAdapter , having the same signatures as Foo ), and continue with Bar . Then the methods you want in Bar can be extracted from the FooAdapter . Unfortunately, your code will need to be modified so that wherever you previously referred to Foo , you could either refer to:

  • Bar , if only the called methods are those that you define in your interface
  • FooAdapter if methods defined in Foo are called, but NOT in Bar .

This method, although clean and a good separation of problems, can be painful and tedious to implement, I'm afraid.

An example of how this will work is shown in the following code snippets:

Third party library

 package org.theirs; public interface Foo { void doSomething(); void doSomethingExtra(); } 

Your code

 package org.mine; public interface Bar { void doSomething(); } public class BarImpl implements Bar{ public void doSomething( /* implementation */ ); } public class FooAdapter implements Bar{ private final Foo adapted; public FooAdapter(Foo adapted) { this.adapted = adapted; } public void doSomething() { adapted.doSomething(); // delegate to adapted instance } } public class UsingThoseBars { public void doSomethingWithAllThoseBars(Collection<Bar> bars) { // each entry in bars could either be a BarImpl or a FooAdapter } } 

In this example, you can see that the doSomethingExtra() method is not available from your code since the Bar interface does not specify it.

Other offers

Note that there may be useful tricks that you could do when rewriting classes, for example with AspectJ. I assume that you will prefer the effect you desire at compile time in pure Java.

Another suggestion is to have a Bar implementation that throws an UnsupportedOperationException for Foo methods that you don't need. Although there is a precedent for major Java libraries (such as the UnmodifiableList in the JDK), I would recommend abandoning this practice altogether. However, if the cost of replacing links to their Foo with your new FooAdapter quite high, this can be a good compromise for using this strategy.

+1
source

All Articles