This is a simplified version of Java inherited Fluent method return type in multiple level hierarchies.
Given the following code:
public enum X {
;
static interface BaseFoo<T, S extends BaseFoo<T, S>> {
S foo();
}
static interface Foo<T> extends BaseFoo<T, Foo<T>> {
void foo1();
}
static interface BaseBar<T, S extends BaseBar<T, S>> extends BaseFoo<T, S> {
S bar();
}
static interface Bar<T> extends BaseBar<T, Bar<T>>, Foo<T> {
void bar1();
}
}
run javac X.java
I get the error message:
X.java:15: error: BaseFoo cannot be inherited with different arguments: <T,X.Bar<T>> and <T,X.Foo<T>>
static interface Bar<T> extends BaseBar<T, Bar<T>>, Foo<T> {
^
Anyone has any solution?
Disclaim: I am trying to use the pattern to implement the fluent interface across a container class inheritance hierarchy.
Background: to make it easier for people to understand why I need this, here is the story. I want to create a container family: Traversal
<- Sequence
<- List
. So Traversal
has a method Traveral<T> accept(Visitor<T>)
(no PECS for short), this method should always return this
after iterating the visitor through the elements. When I have a List
type, I want the method return List<T>
instead of Traversal<T>
because I want to make it possible to call something like myList.accept(v).head(15)
, where head(int)
is a method of List
not Traversal
A class or interface cannot implement or extend from different instantiation of a generic interface. Your Bar
interface is breaking this rule. Let's examine the interface declaration:
static interface Bar<T> extends BaseBar<T, Bar<T>>, Foo<T>
So, Bar<T>
extends two interfaces:
BaseBar<T, Bar<T>>
Foo<T>
In addition to that, those two interfaces extend from different instantiation of the same interface BaseFoo
.
BaseBar<T, S extends BaseBar<T, S>> extends BaseFoo<T, S>
Foo<T> extends BaseFoo<T, Foo<T>>
Those inherited interfaces are eventually also the super interfaces of Bar
interface. Thus your Bar
interface tries to extend from 2 different instantiation of BaseFoo
, which is illegal. Let's understand the reason using a simple example:
// Suppose this was allowed
class Demo implements Comparable<Demo> , Comparable<String> {
public int compareTo(Demo arg) { ... }
public int compareTo(String arg) { ... }
}
then after type erasure, compiler would generate 2 bridge methods, for both the generic method. The class is translated to:
class Demo implements Comparable<Demo> , Comparable<String> {
public int compareTo(Demo arg) { ... }
public int compareTo(String arg) { ... }
// Bridge method added by compiler
public int compareTo(Object arg) { ... }
public int compareTo(Object arg) { ... }
}
So, that results in creation of duplicates bridge method in the class. That is why it is not allowed.
来源:https://stackoverflow.com/questions/19436415/basefoo-cannot-be-inherited-with-different-arguments-t-x-bart-and-t-x-foo