【问题标题】:Java - Bounds on class public APIJava - 类公共 API 的界限
【发布时间】:2017-02-07 07:22:07
【问题描述】:

我有一个 ModelDecorator 助手。我希望它具有以下公共 API

class ModelDecorator<T>{
    public static <T> ModelDecorator<T> create(Class<T> clazz);
    public <SUPER> T from(SUPER fromInstance);
}

所以,给定类 A,B 扩展 A,它可以这样使用:

A a = new A();
B b = ModelDecorator.create(B.class).from(a);

但我想限制 T 和 SUPER,所以我确保只有子类可以使用 API 实例化。此刻,我可以做到:

C c = new C();
B b = ModelDecorator.create(B.class).from(c);

其中 B 不继承自 C。

有什么想法吗?谢谢

【问题讨论】:

标签: java contravariance


【解决方案1】:

我认为约束类型参数T 以扩展类型参数S 的唯一方法是将这些定义放入类定义中:

public class ModelDecorator<S, T extends S> {
    public static <S, T extends S> ModelDecorator<S, T> create(Class<T> clazz) { ... }
    public T from(S instance) { ... }
}

有了这些类

class A {}
class B extends A {}
class C {}

您现在可以编写以下代码:

A a = new A();
B b1 = ModelDecorator.<A, B> create(B.class).from(a); // compiles fine

C c = new C();
B b2 = ModelDecorator.<C, B> create(B.class).from(c); // bound mismatch here

第二个B 创建现在出现编译器错误。

不幸的是,您现在必须显式提供类型参数,因为编译器无法从简单的方法调用 create(B.class) 推断出类型 AC

【讨论】:

  • 这实际上就是现在的样子。我只是不喜欢我的 API :( 我太挑剔了吗?
  • 我对可读性或实用性只字未提。也许您正在尝试使用不合适的技术解决问题 (XY problem)?
  • @Seelenvirtuose 我可能是错的,但createstatic 方法。 public static &lt;S, T extends S&gt; ModelDecorator&lt;S, T&gt; create 中的ST 是否与public class ModelDecorator&lt;S, T extends S&gt; 中的类型相同?如果没有,为static 方法和class 使用不同的类型参数会是更好的选择吗?
  • @CKing 不,静态方法的类型参数与类的类型参数无关。但是......我明确地选择给它们相同的名称,因为create 方法是一个返回ModelDecorator&lt;S, T&gt; 的工厂方法。这里方法的类型参数与类的类型参数的role 完全匹配。在这一点上,我不担心任何混淆。
猜你喜欢
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 2011-02-14
  • 1970-01-01
  • 2019-01-05
相关资源
最近更新 更多