Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java, can I apply an arbitrary interface to an existing class?

Tags:

java

interface

If two classes have some methods of exact same signature, but those methods are not inherited, is there any way to define an interface with the common methods and point both instances of the two classes using the same interface?

For example, suppose a class Cat has boolean isAlive() and another class Dog has boolean isAlive() but Cat and Dog has no common ancestor other than Object and boolean isAlive() is not an inherited method. I cannot modify Cat or Dog because they were written by others. Can I arbitrarily create an interface like that and use it to point a Cat or a Dog?

interface lovable
{
    boolean isAlive();
}

void main()
{
    lovable thing = new Cat(); <-- any syntax to achieve this?
    love(thing);
}

void love(lovable thing)
{
    if (thing.isAlive())
        System.out.println("Aww.");
    else
        System.out.println("Eww.");
}
like image 354
Damn Vegetables Avatar asked Dec 18 '22 19:12

Damn Vegetables


2 Answers

You can create Proxy object as was mentioned in Can you force a java object into implementing an interface at runtime? :

public interface Loveable {
    boolean isAlive();
}

public static class Cat {
    boolean isAlive() {
        return true;
    }
}

public static class Dog {
    boolean isAlive() {
        return false;
    }
}

public static <T> T getWrapper(final Object obj, final Class<T> intface) {
    InvocationHandler invocationHandler = new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return obj.getClass().getDeclaredMethod(method.getName(), method.getParameterTypes()).invoke(obj, args);
        }
    };
    return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), new Class[]{intface}, invocationHandler);
}

public static void main(String[] args) throws Exception {
    System.out.println(getWrapper(new Cat(), Loveable.class).isAlive());
    System.out.println(getWrapper(new Dog(), Loveable.class).isAlive());
}
like image 188
Aleksei Shestakov Avatar answered Dec 21 '22 07:12

Aleksei Shestakov


If you create it by yourself:

public interface Lovable{
    boolean isAlive();
}

public class LovableCat extends Cat implements Lovable{

}

public static void main() {
    Lovable thing = new LovableCat();
    love(thing);
}

If returned from somewhere else:

public interface Lovable{
    boolean isAlive();
}

public class LovableCat implements Lovable{

    private Cat cat;

    public LovableCat(Cat cat){
       this.cat = cat;
    }

    public boolean isAlive(){
       return cat.isAlive();
    }
}

public static void main() {
    Lovable thing = new LovableCat(cat);
    love(thing);
}
like image 39
Ken Bekov Avatar answered Dec 21 '22 08:12

Ken Bekov