Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a Java function's parameter require optional interfaces?

I have two interfaces in Java (version 8) which are very similar. I cannot change the interfaces and cannot change the classes which implement them.

public interface A {
    int get();
}

public interface B {
    int get();
    int somethingelse();
}

Now I have a function that its implementation fits both interfaces (almost). I want it to do something like that:

public int foo((A | B) p) {
    int ret = 0;
    if (p instanceof B) {
        ret = p.somthingelse();
    }
    return ret + p.get();
}

I don't want to use inspection because this function is on the main pipeline of my program. I want it to have good performance. Is it possible to do this in Java?

Edit:

A simple solution will be to copy/paste foo() and implement it differently for each interface. But in reality foo() and the interfaces are much longer than that and I'm trying to avoid code duplication.

like image 542
Liran Funaro Avatar asked Dec 08 '19 16:12

Liran Funaro


People also ask

Can an interface be a parameter Java?

Yes, you can pass Interface as a parameter in the function.

Is it mandatory to implement all the methods of an interface?

Yes, it is mandatory to implement all the methods in a class that implements an interface until and unless that class is declared as an abstract class.

Should you always use an interface Java?

No, every class should not have an interface. It's overkill squared. You use an interface when you need to abstract what's done from how it's done, and you're certain that the implementation can change.


2 Answers

There's unfortunately no way to create that kind of retroactive relationship between two unrelated types.

If you can change foo() and its invocations, you could be able to make use of functional interfaces matching the signatures that you invoke inside foo. I'm using IntSupplier here, with corresponding lambda expressions using concrete implementations of A and B.

Say you have these implementations:

class AImpl implements A {
     //implementation
}
class BImpl implements B {
     //implementation
}

You can change foo to something like:

public int foo(IntSupplier get, IntSupplier somethingElse) {
    int ret = 0;
    if (somethingElse != null) {
        ret = somethingElse.getAsInt();
    }
    return ret + get.getAsInt();
}

And call it this way:

A a = new AImpl();
B b = new BImpl();

int result = this.foo(a::get, b::somethingelse);
like image 144
ernest_k Avatar answered Sep 30 '22 06:09

ernest_k


The only way I can imagine is this:

public int foo(A p) {
    return internal_foo(p);
}

public int foo(B p) {
    return internal_foo(p);
}

private int internal_foo(Object p) {
    if (p instanceof A) {
        return ((A)p).get();
    }
    if (p instanceof B) {
        B b = (B)p;
        ret = b.somthingelse();
        return ret + b.get();
    }
    throw new ClassCastException("Wrong type");
}
like image 36
Zefick Avatar answered Sep 30 '22 07:09

Zefick