2015-07-10 98 views
11

我有三类:嵌套在泛型延伸

class ClassR {} 
class ClassA<T extends ClassR>{}  
class ClassB<E extends ClassA<T extends ClassR>> extends ClassA<T> { 
    void foo(T param) { 
    } 

    void bar(E param) { 
    } 
} 

第三类没有编译,除非我将其更改为

class ClassB<E extends ClassA<T>, T extends ClassR> extends ClassA<T> { 
    void foo(T bar) { 
    } 

    void bar(E param) { 
    } 
} 

有没有办法只保留e参数我需要传递创建ClassB时,T被推断?例如,这将是方便使用:的

new ClassB<ClassA<ClassR>>() 

代替:

new ClassB<ClassA<ClassR>, ClassR>() 
+0

附注:这是更好地实现Runnable接口,而不是扩展Thread。 – m0skit0

+0

更改为ClassR,因为它没有区别 – Nutel

+1

请使用E – Al1en313

回答

0

不知道这是否是你想要的答案,但肯定是最简单的版本上写着:

class ClassR { 
} 

class ClassA<T extends ClassR> { 
} 

class ClassB<T extends ClassR> extends ClassA<T> { 

    void foo(T bar) { 
    } 
} 

public void test() { 
    ClassB<ClassR> classB = new ClassB<>(); 
} 
+0

我的不好,我在ClassB里面同时使用E和T,有没有办法还有E? (更新了问题) – Nutel

1

这种更简单的方法可能适用于您:

class ClassR {} 
class ClassA<T extends ClassR>{}  

class ClassB<T extends ClassR> extends ClassA<T> { 
    void foo(T bar) { 
    } 

    void bar(ClassA<T> param) { 
    } 
} 

和使用再绕过来ClassA任何的引用而成为:

class SubR extends ClassR {} 

ClassB<SubR> obj = new ClassB<SubR>(); 
+0

我认为这是一个很好的答案。从显示的代码判断,'E'永远不会从ClassB中的方法返回。然而,在ClassB中,(例如,在'bar'方法中),你(编译器)只知道它是可以被看作ClassA的东西。因此,你只能以类型安全的方式从ClassA和T中调用方法。因此不需要类型参数'E'。但是,如果存在引用调用“E”方法的ClassB实例的代码,则事情真的不同。 – Sebastian

0

由于E类型扩展ClassA你可以放心地忽略在其声明中的ClassA类型参数。
正确ClassA类型参数在第二个参数中强制执行为ClassB
请参见下面的代码说明:

class ClassB<E extends ClassA, T extends ClassR> extends ClassA<T> { 

    private ClassA ob; 

    public ClassB(E e, T t) { 
    super(t); 
    ob = e; 
    } 

} 

用法示例:

class ClassR { 
    public ClassR() {}; 
} 

class ClassS extends ClassR { 
    private int x; 
    public ClassS(int x) { 
    super(); 
    this.x = x; 
    } 
} 

public static void test() { 
    ClassS data1 = new ClassS(1); 
    ClassB <ClassB, ClassS> first = new ClassB<>(null, data1); 
    ClassS data2 = new ClassS(2); 
    ClassB <ClassB, ClassS> second = new ClassB<>(first, data2); 
} 
+0

使用此解决方案,您可以从ClassA 继承ClassA作为原始类型。无论何时您需要关于'E extends ClassA'中ClassA的泛型类型的信息,您都会丢失。如上所述,我认为存在一些设计缺陷,这阻碍了我们提供良好的实现,因为所示的代码闻起来像隐含的需求。 – Sebastian