英文:
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 {
<T> void updateData(List<T> data);
}
and two implementations of that interface...
public class Version1ApiClient implements ApiClient {
public <Version1DataContract> void updateData(List<Version1DataContract> data) {
// ...
}
}
public class Version2ApiClient implements ApiClient {
public <Version2DataContract> void updateData(List<Version2DataContract> 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
你没有做太多错误的事情;但你跳过了一项命名约定——但这可能掩盖了一个更重要的误解
你认为在这里 <Version1DataContract>
是什么意思?
public <Version1DataContract> void updateData(List<Version1DataContract> data) {
// ...
}
你认为它让 updateData
只与 Version1DataContract
一起工作,而 Version1DataContract
是你的类路径上的一个类,并且在 Version1ApiClient
类的源文件中被导入吗?如果你的答案是肯定的,那么你是错的。这段代码等同于:
public <T> void updateData(List<T> data) {
// ...
}
<Version1DataContract>
只是一个奇怪命名的类型变量。
现在,关于你的问题... 问题在于你在方法中声明了 <Version1DataContract>
作为类型变量,而已经有一个叫做 Version1DataContract
的导入类型,已经是可见的了。这是一个警告,提醒你可能会出现错误。
为了解决你似乎主要的问题,如果你希望 Version1ApiClient
限制 <T> void updateData(List<T> data);
为 T=Version1DataContract
,你不能在不改变接口的情况下做到这一点。你必须更改接口并扩大 T
的范围,以便子类可以“冻结”它:
interface ApiClient<T> {
void updateData(List<T> data);
}
class Version1ApiClient implements ApiClient<Version1DataContract> {
public void updateData(List<Version1DataContract> 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 <Version1DataContract>
does here?
public <Version1DataContract> void updateData(List<Version1DataContract> 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 <T> void updateData(List<T> data) {
// ...
}
<Version1DataContract>
is just a weirdly named type variable.
Now, about your question... The problem is that you have declared <Version1DataContract>
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 <T> void updateData(List<T> 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<T> {
void updateData(List<T> data);
}
class Version1ApiClient implements ApiClient<Version1DataContract> {
public void updateData(List<Version1DataContract> data) {
// ...
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论