Java:抽象方法中的多态返回类型?

时间:2012-05-09 22:19:40

标签: java gwt parametric-polymorphism

我在抽象的java类中有以下代码:

protected abstract <E extends HasText & IsWidget> 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>

有没有办法要求抽象方法返回应该实现多个接口的东西?

注意:不,我无法创建实现我喜欢的两个特殊界面。 GWT有像Label这样已经实现了所述接口的小部件,我想使用这个小部件。

编辑:我想从这里(第22页)这样做:

http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

4 个答案:

答案 0 :(得分:2)

我根据你的问题尝试过,我能够毫无错误地完成任务。请检查我创建的课程。

<强>识别TestClass

public abstract class TestClass {

    protected abstract <E extends HasText & IsWidget > E createNewDisplayWidget();

}

HasText类

public class HasText {

}

<强> IsWidget

public interface IsWidget {

}

<强> DemoClass

 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();

    }

}

当我运行我的主程序时,我总是得到&#34;是的,它可以运行&#34;。请让我知道我错过了什么。

答案 1 :(得分:2)

问题出在Eclipse中。我从3.7升级到3.7.2并且编译器错误消失了。

我不知道这有什么影响的细节。如果有人有线索,请随时更新我的​​答案。

答案 2 :(得分:1)

所以我尝试使用完整的代码来生成错误,但由于某种原因它没有给出错误。稍微调查一下:

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");
    }
}

此代码在我的家用计算机上编译并运行正常但在我的工作计算机上发出错误。

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>

此时我认为这是一个项目设置问题,但我不知道它是什么。 JRE 1.6都是。

答案 3 :(得分:0)

如果Java直接支持拦截类型,那么你想要做的只是

   HasText&IsWidget createNewDisplayWidget();

任何实现都必须返回一个类型为HasText&IsWidget的子类型的对象;换句话说,返回的类型必须是HasTextIsWidget

的子类型

不幸的是,Java不支持这一点。

您可以从两个角度理解您尝试解决的问题:

1)对类型变量的约束是对调用者的约束;调用者提供实际的类型参数,它必须满足约束。你真正想要的是对被叫者的限制。

2)如果类型变量仅出现在返回类型中,而不出现在方法参数类型中,则通常是问题的标志。在Java中,由于邪恶的类型擦除,方法体无法知道运行时类型参数,因此它不能返回调用者所需的正确类型的值,除了{{1}之类的一些微不足道的值。 };另一个琐碎回报值的典型例子是

null