3

I have 2 methods calling same method names:

public void doSomething1(Obj1 obj1) {
    obj1.do1();
    obj1.do2();
    obj1.do3();
}

public void doSomething2(Obj2 obj2) {
    obj2.do1();
    obj2.do2();
    obj2.do3();
}

I would like to extract to "common code" in a third method, this would be possible if I could create a super class of Obj1 and Obj2 but I can't. There is no way make these 2 objects inherit from a super class. So my question is, is there a way in Java to do this kind of extraction when there is no link between objects, something like:

public void doSomething1(Obj1 obj1) {
    refactor(obj1);
}

public void doSomething1(Obj2 obj2) {
    refactor(obj2);
}

private void refactor(NewObj newObj) {
    newObj.do1();
    newObj.do2();
    newObj.do3();
}
3
  • You can do this with a` static` method provided the do1() methods are the same method, not just two methods with the same name. Commented Sep 21, 2016 at 13:37
  • 3
    could you make both of these inherit from an interface? Commented Sep 21, 2016 at 13:37
  • No I can't edit them, these are stub generated classes Commented Sep 21, 2016 at 13:44

4 Answers 4

6

Yes, but it's ugly: Reflection. But before we get to that, let me push back on something in the question:

Use an interface

...this would be possible if I could create a super class of Obj1 and Obj2 but I can't. There is no way make these 2 objects inherit from a super class.

They don't have to: They can just implement the same interface, without inheriting from the same superclass:

public interface TheCommonInterface {
    void do1();
    void do2();
    void do3();
}

public class Obj1 implements TheCommonInterface {
    // ...
}

public class Obj2 implements TheCommonInterface {
    // ...
}

Then

private void refactor(TheCommonInterface obj) {
    obj.do1();
    obj.do2();
    obj.do3();
}

Use a wrapper

If for some reason you can't even add an interface, use a wrapper class (an adapter class) that implements the interface.

Use reflection

In the worst case, you can use reflection: Use any of the several mechanisms on Class that let you find methods (such a getMethod), and then use Method#invoke on that method:

public void refactor(Object obj) {
    Class cls = obj.getClass();
    cls.getMethod("do1").invoke(obj);
    cls.getMethod("do2").invoke(obj);
    cls.getMethod("do3").invoke(obj);
}

That example is re-discovering the methods every time. If you ran into a performance problem doing that, you might look at caching them.

Sign up to request clarification or add additional context in comments.

4 Comments

Obj1 ans Obj2 are not editable, they are generated classes
@Ferdossi: That leaves you with wrappers or reflection, then, if whatever generates them doesn't have the configurability to add an interface definition (which is surprising).
They are generated separately and are part of complete different jars
@Ferdossi: It doesn't matter if they're in different jars (consider: any time you implement an interface from the JDK, you're implementing an interface from a different jar), and it doesn't really matter if they're generated separately. But again, if you can't do #1 above, you still have #2 and #3.
3

If the method body is the exactly the same, then they should inherit from a parent because they share a feature.

Alternatively, you can create an interface to share a behavior between the classes. But this will require implementing the body of the interface in both classes implementing it

Comments

2

You could use a static method

private static void refactor(NewObj newObj) {
    newObj.do1();
    newObj.do2();
    newObj.do3();
}

However, both object classes need to have a common interface NewObj in which case you can add this method to the interface:

interface NewObj {
    default void do123() {
        do1();
        do2();
        do3();
    }

    void do1();
    void do2();
    void do3();
}

Comments

1

You can create an interface with common methods.

After you can modify the original classes to implements those methods.

Then you can use the new created interface instead of Object as parameter in the function.

public interface DoOperations {
    void do1();
    void do2();
    void do3();
}

In the Obj1, Obj2 classes you need only to implements DoOperations

public Obj1 implements DoOperations {
    ....
}

public Obj2 implements DoOperations {
    ....
}

To call it:

public void doSomething(DoOperations obj) {
    obj.do1();
    obj.do2();
    obj.do3();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.