Java 泛型类之间的依赖关系

Java 泛型类之间的依赖关系,java,generics,Java,Generics,我有以下接口: public interface Assembler<T, S> { S assemble( T val); } public interface Slicer<T, V> { V[] slice(T val); } 公共接口汇编程序{ S组装(T-val); } 公共接口切片器{ V[]切片(T值); } 我想让汇编器实例使用切片器实例并调用它的slice()。我有以下资料: public class MyAssembler<T,

我有以下接口:

public interface Assembler<T, S> {
   S assemble( T val);
}

public interface Slicer<T, V> {
   V[] slice(T val);
}
公共接口汇编程序{
S组装(T-val);
}
公共接口切片器{
V[]切片(T值);
}
我想让汇编器实例使用切片器实例并调用它的slice()。我有以下资料:

public class MyAssembler<T, S> implements Assembler<T, S> {

   private final Slicer<T, V> slicer;

   //ctor
   public MyAssembler() {
     slicer = new MySlicer<T, V>();
   }

   @Override
   public S assemble(T val) {         
      V[] v = mySlicer.slice(val);
    }
公共类MyAssembler实现汇编程序{
私人最终切片机;
//执行器
公共MyAssembler(){
切片器=新的MySlicer();
}
@凌驾
公众集会(T val){
V[]V=mySlicer.slice(val);
}

这不会编译,因为V类型未知(无法解析为类型)在MyAssembler中。我无法将Assembler接口更改为
Assembler
。是否有其他方法可以定义依赖项?这不是非泛型类的问题。即使使用静态工厂方法获取对切片器的引用,未知V的问题仍然存在。有什么建议吗?如果不能这样做,可以吗我们推荐一种不同的方法或设计模式,允许汇编器调用切片器的切片()?

继承将解决您的问题,而不是在这种情况下组合,如下所示:

public class MyAssembler<T,S,V> extends MySlicer<T,V> implements Assembler<T,S> {

    public MyAssembler() {
    }

    @Override
    public S assemble(T val) {
        V[] v = this.slice(val);
        ...
    }
} 
公共类MyAssembler扩展MySlice实现汇编程序{
公共MyAssembler(){
}
@凌驾
公众集会(T val){
V[]V=此.slice(val);
...
}
} 

汇编程序是否总是将切片器作为其两个泛型之一?如果是,您只需要定义一个泛型,并将切片器作为非泛型成员变量


但是,如果泛型类型可能是切片器,也可能不是切片器,那么当其中一个类型是具有反射的切片器时,可以实现特殊处理,尤其是
If(v instanceof Slicer)
,如果为真,则将其转换为切片器。

由于您的
S
V
是泛型的,因此您可以将它们转换为任何其他类型,甚至其他泛型。您可以执行以下操作:

public class MyAssembler<T, S> implements Assembler<T, S> {

    private final Slicer<T, S> slicer;

    public MyAssembler() {
        slicer = new MySlicer<T, S>();
    }

    @Override
    public S assemble(T val) {
        S[] v = slicer.slice(val);
        return v[0]; // for example
    }
}
公共类MyAssembler实现汇编程序{
私人最终切片机;
公共MyAssembler(){
切片器=新的MySlicer();
}
@凌驾
公众集会(T val){
S[]v=切片器切片(val);
返回v[0];//例如
}
}

我所做的是将
T
S
定义为相同的类型。在我自己的实现中,我可以毫无问题地做到这一点。

重新发布Sotirios Delimanolis的评论作为答案


要允许在MyAssembler中使用V,请声明
MyAssembler扩展Assembler
。要使用它,请使用for ex:
Assembler asmblr=new MyAssembler

实例化。您可以为
MyAssembler
声明第三种类型变量。我尝试使用
MyAssembler
。它会编译,但一旦尝试实例化例如:
Assembler asmblr=new MyAssembler
编译失败,原因是:类型Assembler的参数数量不正确;无法使用参数对其进行参数化。第三个类型参数是
MyAssembler
所必需的,而不是声明的类型,
Assembler
所必需的。但它在这里似乎不是很有用,因为您没有执行任何操作使用
V
的nything。在实际用例中,假设将使用V。但是,您将无法通过它使用类型
Assembler
的引用。切片器将不是Assembler中的泛型类型t或S之一。这可能会在假设类型始终相同的情况下起作用,但这不限制S和原始V现在是相同的t吗ype?可能希望Assember S是字符串,切片器V是整数。确实如此。但是正如您所指出的,汇编程序应该调用切片器的切片()。如果类型S和V不同,则无法保证任何内容。如何将
V'强制转换为
S
?通过调用
slice`您有一个
V
,但在
assemble
中,您希望返回
S
。如果您希望支持任意类型,则无法执行此操作。但是:如我的示例所示,您无法选择切片器的类型。它将由汇编器的类型决定。由于切片器封装得很好,您甚至不知道在汇编器后面有什么东西可以完成这项工作。您只需使用行为类似于黑匣子的汇编器。我认为现在在汇编器中使用V更灵活:
MyAssembler Extendes assembler