In Java, how can I implement a non-generic interface which has methods that use generics using concrete types?

huangapple go评论77阅读模式
英文:

In Java, how can I implement a non-generic interface which has methods that use generics using concrete types?

问题

我有一个接口...

public interface ApiClient {
    <T> void updateData(List<T> data);
}

和该接口的两个实现...

public class Version1ApiClient implements ApiClient {
    public <Version1DataContract> void updateData(List<Version1DataContract> data) {
        // ...
    }
}
public class Version2ApiClient implements ApiClient {
    public <Version2DataContract> void updateData(List<Version2DataContract> data) {
        // ...
    }
}

我在这两个实现中都得到了这个错误...

类型参数 'Version#DataContract' 隐藏了可见类型 'com.company.package.Version#DataContract'

...其中 # 是相应实现的数字。

我做错了什么?另外,在这种情况下,接口不能直接有一个类型参数,它只能存在于方法中。

英文:

I have an interface...

public interface ApiClient {
    &lt;T&gt; void updateData(List&lt;T&gt; data);
}

and two implementations of that interface...

public class Version1ApiClient implements ApiClient {
    public &lt;Version1DataContract&gt; void updateData(List&lt;Version1DataContract&gt; data) {
        // ...
    }
}
public class Version2ApiClient implements ApiClient {
    public &lt;Version2DataContract&gt; void updateData(List&lt;Version2DataContract&gt; data) {
        // ...
    }
}

I get this error in both of the implementations...

> Type parameter 'Version#DataContract' hides visible type 'com.company.package.Version#DataContract'

...where the # is the number for that respective implementation.

What have I done wrong? Also, in this use case the interface cannot have a type parameter on it directly. It can only be on the method.

答案1

得分: 2

你没有做太多错误的事情;但你跳过了一项命名约定——但这可能掩盖了一个更重要的误解

你认为在这里 &lt;Version1DataContract&gt; 是什么意思?

public &lt;Version1DataContract&gt; void updateData(List&lt;Version1DataContract&gt; data) {
    // ...
}

你认为它让 updateData 只与 Version1DataContract 一起工作,而 Version1DataContract 是你的类路径上的一个类,并且在 Version1ApiClient 类的源文件中被导入吗?如果你的答案是肯定的,那么你是错的。这段代码等同于:

public &lt;T&gt; void updateData(List&lt;T&gt; data) {
    // ...
}

&lt;Version1DataContract&gt; 只是一个奇怪命名的类型变量。

现在,关于你的问题... 问题在于你在方法中声明了 &lt;Version1DataContract&gt; 作为类型变量,而已经有一个叫做 Version1DataContract 的导入类型,已经是可见的了。这是一个警告,提醒你可能会出现错误。


为了解决你似乎主要的问题,如果你希望 Version1ApiClient 限制 &lt;T&gt; void updateData(List&lt;T&gt; data);T=Version1DataContract,你不能在不改变接口的情况下做到这一点。你必须更改接口并扩大 T 的范围,以便子类可以“冻结”它:

interface ApiClient&lt;T&gt; {
	void updateData(List&lt;T&gt; data);
}

class Version1ApiClient implements ApiClient&lt;Version1DataContract&gt;  {
	public void updateData(List&lt;Version1DataContract&gt; data) {
		// ...
	}
}
英文:

You didn't do much that's wrong; but you skipped a naming convention - but that could be hiding a more important misunderstanding

What do you think &lt;Version1DataContract&gt; does here?

public &lt;Version1DataContract&gt; void updateData(List&lt;Version1DataContract&gt; data) {
    // ...
}

Do you think it makes updateData work just with Version1DataContract, which is a class on your classpath and imported in the source file of your Version1ApiClient class? If your answer is yes, then you're mistaken. That code is equivalent to:

public &lt;T&gt; void updateData(List&lt;T&gt; data) {
    // ...
}

&lt;Version1DataContract&gt; is just a weirdly named type variable.

Now, about your question... The problem is that you have declared &lt;Version1DataContract&gt; as a type variable on a method, while there is an imported type called Version1DataContract, and that is already visible. This is a warning alerting you to potential bugs.


To address what seems to be your main issue, if you need Version1ApiClient to limit &lt;T&gt; void updateData(List&lt;T&gt; data); to T=Version1DataContract, you can't do it without changing the interface. You'd have to change your interface and broaden the scope of T so that the subclass can "freeze" it:

interface ApiClient&lt;T&gt; {
	void updateData(List&lt;T&gt; data);
}

class Version1ApiClient implements ApiClient&lt;Version1DataContract&gt;  {
	public void updateData(List&lt;Version1DataContract&gt; data) {
		// ...
	}
}

huangapple
  • 本文由 发表于 2020年10月1日 03:56:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/64144847.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定