简体   繁体   中英

Java code reuse without inheritance

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();
}

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.

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

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();
}

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM