11

我在抽象 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

4 回答 4

2

我已经根据您的问题进行了尝试,并且能够顺利通过。请检查我创建的课程。

测试类

public abstract class TestClass {

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

}

HasText 类

public class HasText {

}

小部件

public interface IsWidget {

}

演示类

 public class DemoClass extends HasText implements IsWidget{

    }

测试类1

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

    }

}

当我运行我的主程序时,我总是得到“是的,它可以工作”。请让我知道我错过了什么。

于 2012-05-09T23:53:39.090 回答
2

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

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

于 2012-05-10T19:49:29.017 回答
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 两者。

于 2012-05-10T07:38:34.743 回答
0

你想做的只有当Java直接支持拦截类型时才有可能,那么你可以简单地

   HasText&IsWidget createNewDisplayWidget();

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

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

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

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

2) 如果一个类型变量只出现在返回类型中,而没有出现在方法参数的类型中,这通常是问题的征兆。在 Java 中,由于邪恶的类型擦除,方法体无法知道运行时类型参数,因此它无法返回调用者所需的正确类型的值,除了一些琐碎的值,如null; 平凡返回值的另一个经典例子是

java.util.Collections  
    <T> Set<T> emptySet()
于 2012-05-10T04:52:29.330 回答