Java:抽象方法中的多态返回类型?
我在抽象java类中有以下代码:Java:抽象方法中的多态返回类型?,java,gwt,parametric-polymorphism,Java,Gwt,Parametric Polymorphism,我在抽象java类中有以下代码: protected abstract <E extends HasText & IsWidget> E createNewDisplayWidget(); 受保护的抽象E createNewDisplayWidget(); 这很好。但是,如果我在任何地方调用它,编译器都会抱怨: Bound mismatch: The generic method createNewDisplayWidget() of type DemoClass is
protected abstract <E extends HasText & IsWidget> E createNewDisplayWidget();
受保护的抽象E createNewDisplayWidget();
这很好。但是,如果我在任何地方调用它,编译器都会抱怨:
Bound mismatch: The generic method createNewDisplayWidget() of type DemoClass is not applicable for the arguments (). The inferred type HasText is not a valid substitute for the bounded parameter <E extends HasText & IsWidget>
绑定不匹配:DemoClass类型的泛型方法createNewDisplayWidget()不适用于参数()。推断的类型HasText不是有界参数的有效替代品
有没有一种方法需要一个抽象方法来返回应该实现多个接口的东西
注意:不,我无法创建实现我喜欢的两个接口的特殊接口。GWT有像Label这样的小部件,它已经实现了上述接口,我想使用上述小部件
编辑:我从这里得到了这样做的想法(第22页):
根据您的问题,我已经尝试过了,我能够顺利通过。请检查我创建的类 TestClass
public abstract class TestClass {
protected abstract <E extends HasText & IsWidget > E createNewDisplayWidget();
}
public class HasText {
}
public class DemoClass extends HasText implements IsWidget{
}
IsWidget
public interface IsWidget {
}
DemoClass
public abstract class TestClass {
protected abstract <E extends HasText & IsWidget > E createNewDisplayWidget();
}
public class HasText {
}
public class DemoClass extends HasText implements IsWidget{
}
TestClass1
public class TestClass1 extends TestClass{
@Override
protected DemoClass createNewDisplayWidget() {
// TODO Auto-generated method stub
DemoClass type = new DemoClass();
return type;
}
public void checkOut(){
if(createNewDisplayWidget() instanceof HasText || createNewDisplayWidget() instanceof IsWidget){
System.out.println("Yes it works");
}
else{
System.out.println("It doesnt");
}
}
public static void main(String[] args){
TestClass1 check = new TestClass1();
check.checkOut();
}
}
当我运行我的主程序时,我总是得到“是的,它能工作”。请让我知道我是否遗漏了什么。只有在Java直接支持拦截类型的情况下,您才可能想做什么,然后您可以简单地
HasText&IsWidget createNewDisplayWidget();
任何实现都必须返回属于HasText&IsWidget
类型的子类型的对象;换句话说,返回的类型必须是HasText
和IsWidget
不幸的是,Java不支持这一点
您试图解决的问题可以从两个角度来理解:
1) 对类型变量的约束是对调用方的约束;调用者提供实际的类型参数,并且它必须满足约束。您真正想要的是对被调用方的约束
2) 如果类型变量只出现在返回类型中,而不出现在方法参数的类型中,则通常是问题的迹象。在Java中,由于邪恶的类型擦除,方法体无法知道运行时类型参数,因此它无法返回调用者所需的正确类型的值,除了一些琐碎的值,如null
;另一个简单返回值的经典示例是
java.util.Collections
<T> Set<T> emptySet()
java.util.Collections
设置清空集()
所以我尝试编写完整的代码来生成错误,但由于某种原因,它没有给出错误。我们将在稍后进行调查:
import java.util.LinkedList;
public abstract class DemoClass {
public static void main(String[] args) {
DemoClass dc = new DemoClassImpl();
dc.createNewLivingAndDying().live();
dc.killAll();
}
LinkedList<Dies> dying = new LinkedList<Dies>();
public Lives createNewLivingAndDying() {
Lives ab = newLivingAndDying(); // This is where I expected an error
dying.add((Dies) ab);
return ab;
}
public void killAll() {
for (Dies dead : dying)
dead.die();
}
protected abstract <E extends Lives & Dies> E newLivingAndDying();
}
class DemoClassImpl extends DemoClass {
@SuppressWarnings("unchecked")
@Override
protected <E extends Lives & Dies> E newLivingAndDying() {
return (E) new SomePrivateClass(); // This is what I don't understand
}
}
interface Lives {
public void live();
};
interface Dies {
public void die();
};
class SomePrivateClass implements Lives, Dies {
@Override
public void die() {
System.out.println("Object Dies");
}
@Override
public void live() {
System.out.println("Object Lives");
}
}
import java.util.LinkedList;
公共抽象类DemoClass{
公共静态void main(字符串[]args){
DemoClass dc=新的DemoClassImpl();
dc.createnewlivingandding().live();
dc.killAll();
}
LinkedList=新建LinkedList();
公共生活创造新生活和新死亡(){
Lives ab=newlivingandding();//这就是我预期的错误所在
死亡。添加((死亡)ab);
返回ab;
}
公众假期{
因为(死了:死了)
死了,死了;
}
受保护的摘要E newliving and ding();
}
类DemoClassImpl扩展了DemoClass{
@抑制警告(“未选中”)
@凌驾
受保护的新生活和死亡(){
return(E)new SomePrivateClass();//这是我不明白的
}
}
接口寿命{
公共空间活动();
};
接口{
公共无效死亡();
};
类someprivate类实现生命,死亡{
@凌驾
公共空间(){
System.out.println(“对象死亡”);
}
@凌驾
公共生活{
System.out.println(“对象寿命”);
}
}
此代码在我的家用计算机上编译并运行良好,但在我的工作计算机上给出了错误
Bound mismatch: The generic method newLivingAndDying() of type DemoClass is not applicable for the arguments (). The inferred type Lives is not a valid substitute for the bounded parameter <E extends Lives & Dies>
绑定不匹配:DemoClass类型的泛型方法newlivingandding()不适用于参数()。推断的类型不是有界参数的有效替代品
在这一点上,我认为这是一个项目设置问题,但我不知道它是什么。JRE 1.6两者都有。问题出在Eclipse中。我从3.7升级到3.7.2,编译器错误消失了
我不知道这有什么影响的细节。如果有人有线索,请随时更新我的答案。您是否尝试用逗号而不是and?逗号表示绑定以IsWidget结尾。然后HasText就被忽略了。编译器抛出一个警告,说第二种类型是“隐藏的”。你能给我们看一下你的一个/一些调用站点吗?@McTrafik Ok,很高兴知道:)我认为这实际上是不可能的。返回该交叉点中的一个实际类。您正在从同一个类调用
createNewDisplayWidget()
,在该类中,您为它提供了一个更具体的返回类型。我尝试从DemoClass
调用它,但无法重现OP的错误。也许这是GWT特有的问题,是的。我试图解决的问题是不必创建另一种类型,如“DemoClass”。这实际上是我使用的解决方案,但不是我想要的,因为现在我必须为我想要使用的GWT中的每个类创建自定义类型。答案是不正确的,您不应该接受它。正确的是,这样的方法签名可能是问题的标志。但是对于创建特定子类型集的工厂来说,这可能是可以的(为了方便),并且它可以在Java中工作(只需添加“@SuppressWarnings”(“unchecked”),如果您愿意的话。您可能会在运行时得到ClassCastException,这可能不是最好的方法,但这并不能解释您得到的编译器错误!对我来说,在Java中,由于邪恶的类型擦除,方法体无法知道运行时类型参数,因此它无法返回调用者所需的正确类型的值de sense作为原因。我尝试向签名添加类型为E
的参数,编译器停止抱怨。当然,然后该方法变得不可用。换句话说,通过使用Object
(隐式)作为类型参数和