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>

複数のインターフェースを実装する必要があるものを返すために抽象メソッドを要求する方法はありますか?

注:いいえ、好きな2つを実装する特別なインターフェースを作成することはできません。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{

    }

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

    }

}

メインプログラムを実行すると、常に「はい、動作します」と表示されます。何か足りないので教えてください。

于 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&IsWidgetHasTextつまり、返される型はとの両方のサブタイプでなければなりません。IsWidget

残念ながら、Java はそれをサポートしていません。

解決しようとした問題は、次の 2 つの角度から理解できます。

1) 型変数の制約は、呼び出し元の制約です。caller は実際の型引数を提供し、制約を満たさなければなりません。本当に必要なのは、呼び出し先に対する制約です。

2) 型変数が戻り値の型だけに現れ、メソッド パラメーターの型には現れない場合、通常は問題の兆候です。Java では、悪意のある型 eraserが原因で、メソッド本体は実行時の型引数を認識できないため、呼び出し元が必要とする適切な型の値を返すことができませんnull。些細な戻り値のもう 1 つの古典的な例は次のとおりです。

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