Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interfaces - solving ambiguous error

Tags:

java

interface

Lets look at the following example:

public class BothPaintAndPrintable implements Paintable,Printable{
    public void print() {}
    public void paint() {}
}
public interface Paintable {
    public void paint();
}

public interface Printable {
    public void print();
}

public class ITest {
    ArrayList<Printable> printables = new ArrayList<Printable>();
    ArrayList<Paintable> paintables = new ArrayList<Paintable>();
    public void add(Paintable p) {
        paintables.add(p);
    }
    public void add(Printable p) {
        printables.add(p);
    }
    public static void main(String[] args) {
        BothPaintAndPrintable a= new BothPaintAndPrintable();
        ITest t=new ITest();
        t.add(a);//compiliation error here
    }
}

What if I want BothPaintAndPrintable instances to be added to each of the ArrayLists? One way would be overloading the method with a BothPaintAndPrintable parameter, but I'm trying to see alternatives since doing that might reduce code reuseability. Does anyone have another idea?

like image 573
Ofek Ron Avatar asked Aug 01 '12 15:08

Ofek Ron


People also ask

Why there is no ambiguity in interface?

If B & C are interfaces, then there is no implementation in the interfaces. Even if B & C override the method in interface A (cannot be a class), the methods will have same signature. There is no ambiguity regarding which implementation to use, because there is no implementation.

What is an ambiguity error?

Ambiguity errors occur when erasure causes two seemingly distinct generic declarations to resolve to the same erased type, causing a conflict.

How does Java avoid diamond problems?

Java avoids the multiple inheritance problem for classes by allowing a class to extend only one other class. Class D can implement many interfaces.


1 Answers

You need a third overload:

public <T extends Object&Paintable&Printable> void add(T t) {
  paintables.add(t);
  printables.add(t);
}

This makes the erasure add(Object), so it doesn't conflict with the other methods, but it does restrict the input to implementors of both Paintable and Printable.

(Guava had to use this trick for Joiner with Iterator and Iterable, because some evil classes out there implemented both, even though it's a terrible idea.)

like image 158
Louis Wasserman Avatar answered Sep 18 '22 12:09

Louis Wasserman