1

我对结构的创建有一个困惑:一个表示一般物理转换的接口 Transform 和一个表示特定类型转换的 PoincareTransform 类。我想做这样的事情

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

public class PoincareTransform implements Transform {
   private Matrix matrix;
   public Transform compose(Transform t) {
   ...
   }
}

但我希望该方法 compose(Transform T) 仅采用 PoicareTransform 因为必须有一个矩阵来组合。一个可能的解决方案是使用泛型

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 子类现在和以前一样有问题。此外,有了这个定义,我的项目周围都有泛型!

我在概念上是错误的?我怎么能建造这样一个我想到的结构?

4

2 回答 2

0

我想我会采用您的第一个解决方案,但如果您无法从PoincareTransform.transform(Transform t).

例如:

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;
     ...
   }
}
于 2013-08-19T19:15:11.967 回答
0

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

恕我直言,最干净的解决方案是放弃编译时检查并解决运行时检查的想法:在子类型中使用 instanceof 以确保参数是正确的 Transform 子类型(如我之前的海报所示)。

于 2013-08-19T19:42:11.173 回答