【问题标题】:Can you reference 'this' class as a generic parameter? [duplicate]您可以将“this”类作为通用参数引用吗? [复制]
【发布时间】:2016-03-07 12:59:37
【问题描述】:

有几次我遇到了一些问题,我想做这样的事情:

interface MyInterface
{
    public Validator<this.class> getValidator();
}

class MyInstance implements MyInterface
{
     public Validator<this.class> getValidator()
     {
          //do stuff
     }
}

因此,为了能够将具体类的引用作为泛型参数传递,当您拥有作用于当前类的类时,通常需要它。一个简单的解决方案是使用 ?类型,但是当您需要访问类本身中的值时(例如,如果您需要执行 getValidator().validateForm().getField() 之类的操作)或者即使您想使用链式方法对类进行子类化(例如 StringBuilder.append()),这并不理想

我通常不得不这样做:

interface MyInterface<T>
{
    public Validator<T> getValidator();
}

class MyInstance implements MyInterface<MyInstance>
{
     public Validator<MyInstance> getValidator()
     {
          //do stuff
     }
}

但是这样比较难看,很容易不小心把错误的类作为参数。

还有其他解决方案吗?


编辑:“有没有办法用类型变量引用当前类型?”提供的答案目前没有解决这个问题(除了Scala的答案)

【问题讨论】:

  • 我不确定this.class 应该代表什么。它应该代表Class&lt;MyInterface&gt;吗?我不明白你的问题
  • 我的意思是它应该引用扩展 MyInterface 的具体类,所以在这种情况下它应该最终成为 MyInstance,但如果另一个类(比如 AnotherInstance)扩展 MyInterface,getValidator() 会返回一个验证器
  • 如前所述,这也是链式方法的问题,因此假设您想将 StringBuilder 扩展为一个新类ErrorBuilder,并添加另一个链式方法,假设appendError(),如果你这样做new ErrorBuilder().appendError("Error").append("Here") 可以正常工作,因为 appendError() 将返回 ErrorBuilder 的类,但是如果您这样做 new ErrorBuilder().append("Here").appendError("Error") 它将失败,因为 append 返回一个 StringBuilder!如果您可以拥有像public this.class append(String x) 这样的签名,那就太理想了
  • 答案并不能解决问题,因为它无法解决您的问题。您想要的不是 Java 类型系统中的类型安全。看我的回答。

标签: java generics


【解决方案1】:

你想要的都是不可能的。

原因与您不能将List&lt;Dog&gt; 分配给List&lt;Animal&gt; 的原因相同。

如果你想要的是可能的,你可以有一个实现:

class MyInstance implements MyInterface
{
     public Validator<MyInstance> getValidator()

但是,在您的界面中,getValidator() 的返回类型被“定义”为Validator&lt;MyInterface&gt;(因为在界面上下文中this.class 指的是MyInterface

而且您不能将Validator&lt;MyInstance&gt; 分配给Validator&lt;MyInterface&gt;

这样做的原因是,如果你能做到这一点,你可以有另一个类返回一个Validator&lt;MyOtherInstance&gt;,你也可以分配给Validator&lt;MyInterface&gt;。然后,当您尝试调用 Validator&lt;MyInstance&gt; 上的方法时,您现在不知道它是采用 MyInstance 还是 MyOtherInstance 对象。

【讨论】:

    【解决方案2】:

    我不相信除了你的“通常”之外,没有任何其他方法可以得到你所追求的东西。

    但是,作为替代方案,您可以考虑:

    interface MyInterface {
        Validator<? extends MyInterface> getValidator();
    }
    

    其中MyInterface 还定义了验证器所需的访问器方法。 (注意MyInstance 的实现仍然可以返回Validator&lt;MyInstance&gt;。)

    visitor pattern 可能是改变设计以解决此问题的另一种方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-16
      • 2016-06-16
      • 2012-09-22
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      • 2014-07-30
      相关资源
      最近更新 更多