java:泛型结构之谜

java:泛型结构之谜,java,generics,structure,Java,Generics,Structure,我有一个关于结构创建的难题:一个表示一般物理转换的接口转换,以及一个表示特定类型转换的PoincareTransform类。我想做这样的事 public interface Transform { public Transform compose(Transform t); } public class PoincareTransform implements Transform { private Matrix matrix; public Transform compos

我有一个关于结构创建的难题:一个表示一般物理转换的接口转换,以及一个表示特定类型转换的PoincareTransform类。我想做这样的事

public interface Transform {
   public Transform compose(Transform t);
}

public class PoincareTransform implements Transform {
   private Matrix matrix;
   public Transform compose(Transform t) {
   ...
   }
}
但我希望composetTransform T方法只采用poiceransform,因为它需要一个矩阵来组合。一种可能的解决方案是使用泛型

public interface Transform<T extends Transform<T>> {
   public T compose(T t);
}

public class PoincareTransform implements Transform<PoincareTransform> {
   private Matrix matrix;
   public PoincareTransform compose(PoincareTransform t) {
   ...
   }
}
但这并不令人满意,因为它在概念上不干净、不优雅,而且还有一些麻烦:庞加莱变换子类现在和以前有同样的问题。而且,有了这个定义,我的项目周围就有了泛型


我在概念上错了?我怎么能建立这样一个我心目中的结构呢?

我想我会选择你的第一个解决方案,但是如果你不能从PoincareTransform.transformt中的给定变换中得到矩阵,我会返回一个错误

例如:

public class PoincareTransform implements Transform {
   private Matrix matrix;
   public Transform compose(Transform t) {
     if (!t.hasMatrix()) {
       // Throw an exception, or some other meaningful error.
     }
     ...
   }
}
通过这种方式,它是通用的,因此如果您最终使用不同类型的矩阵变换,那么您可以使用它

另一方面,如果您确实只想对PoincareTransforms进行操作,则可以使用instanceof操作符检查传入的实例是否正确

public class PoincareTransform implements Transform {
   private Matrix matrix;
   public Transform compose(Transform t) {
     if (!t instanceof PoincarTransform) {
       // Throw an exception, or some other meaningful error.
     }
     PoincarTransform p = (PoincarTransform)t;
     ...
   }
}

你说的是协变参数类型,我不相信你能在java的类型系统中对其进行编码。这将违反Liskov的原则:如果超类型声明它可以接受某些类型T的值,子类型必须至少接受同样多的值。但允许的是逆变参数类型:在您的情况下,子类型可以接受比其超类型更多的类型,Liskov将允许PoincoreTransform.compose接受对象而不是转换,但java中同样不支持这种情况


我认为最干净的解决方案是放弃编译时检查的想法,而改为运行时检查:使用子类型中的instanceof来确保参数是正确的转换子类型,如我前面的海报所示。

PoincareTransform子类现在和以前有同样的问题。-我想你提到的问题是用泛型解决的。你能详细说明一下你的具体问题吗?如果我扩展庞加莱变换得到一个更具体的变换类,比如说洛伦兹变换,那么洛伦兹变换可以与更一般的庞加莱变换组合,如果这不是一个和前面一样严重的问题,我不鼓励这样做。但更糟糕的是,我在项目中到处都有泛型,因为当我使用转换时,我需要保存一个泛型…可能是See:and的副本,它看起来像是代表一个类型树,即Transform->PoincareTransform->LorentzTransform。为什么不将Transform创建为抽象类而不是接口,并提供compose方法的实现以引发不受支持的异常呢。这样,只有重写此默认行为的子类才能使用compose方法。Transform类应声明为公共接口Transform。“extends Transform”无效我必须使用反射我不清楚这一点来返回错误?没有更简单的方法吗?