5

Elementという基本クラスがあります。他のいくつかのクラス(LabelやImageなど)は両方ともこのクラスを拡張します。

これで、次のメソッドを持つディスパッチクラスができました。

public class Dispatcher {
    public static AbstractPropertyEditor<Label> createEditor(Label e) {
    ...
    }

    public static AbstractPropertyEditor<Element> createEditor(Element e) {
    ...
    }
}

Label(Elementを拡張する)のインスタンスがあり、それをに渡したい場合createEditor()、なぜ最も一般的なメソッド(2番目のメソッド)が呼び出されるのですか?最も具体的なメソッド(createEditor(Label e))が呼び出されるのは正常ではないでしょうか。

a)Elementを実装しているが、このディスパッチングクラスに独自の特定のメソッドを持たないすべてのクラスを「キャッチ」するには、Element-paramを使用したメソッドが絶対に必要です。

Java 6を使用していますが、これを「修正」するにはどうすればよいですか?

編集:さて、私はそれがジェネリックについてはまったくないことを認めなければなりません。しかし、それは私が最初にそれに遭遇した場所です。

ありがとう、よろしく

4

5 に答える 5

6

どうしてですか:

  • デフォルトの実装を提供するElement抽象クラスを作成しますcreateEditor()
  • LabelオーバーライドしますcreateEditor()

したがって、静的ユーティリティは必要なく、目標を達成できます。

Elementインターフェイスである必要がある場合は、次のようにします。

  • createEditor()のメソッドとして定義するElement
  • EditorFactoryインターフェイスを定義する
  • 提供DefaultEditorFactoryし、ListEditorFactory
  • の実装者で適切なファクトリを使用しますElement

    public Editor createEditor() {
         editorFactory.createEditor(this);
    }
    

ここで、コンクリートEditorFactoryは初期化中またはある種の依存性注入によってインスタンス化されます。


あなたの具体的な質問によると-それはあなたがそこでコンパイルしたタイプに依存します。あなたがそれを呼ぶかどうかはそれがそうであるかどうかcreateEditor(obj)に依存しますElement obj = ..Label obj = ..

于 2010-02-14T21:14:53.090 に答える
2

これは実際にはジェネリックスとはほとんど関係がなく、メソッドのオーバーロードとはすべて関係があります。Javaでは、呼び出されるメソッドシグネチャは実行時ではなくコンパイル時に決定されるため、実行時にチェックしてキャストする必要があります。

したがって、これを置き換えます。

 Element label = getLabel();
 AbstractPropertyEditor<?> editor = createEditor(label);   

これとともに:

 Element label = getLabel();
 AbtractPropertyEditor<?> editor;
 if(label instanceof Label) {
      editor = createEditor((Label) label);
 } else {
      editor = createEditor(label);
 }

これを修正するもう1つの(より標準的/より良い)方法は、createEditor(Element)メソッドにタイプをチェックさせ、キャストを使用してサブタイプの正しいオーバーロードされたメソッドを呼び出すことです。ただし、宣言されたメソッドでそれを行うと、戻りパラメーターに問題が発生します。

于 2010-02-14T21:08:37.917 に答える
1

Java言語仕様から:

メソッドが呼び出されると(§15.12)、実際の引数の数(および明示的な型の引数)と引数のコンパイル時の型が、コンパイル時に使用され、呼び出されるメソッドのシグネチャが決定されます( §15.12.2)。呼び出される メソッドがインスタンスメソッドである場合、呼び出される実際のメソッドは、動的メソッドルックアップ(§15.12.4)を使用して実行時に決定されます。

于 2010-02-14T21:26:59.817 に答える
0

これはオーバーロードされたメソッドの例です。実行時の実際のオブジェクトは要素ではなくラベルですが、呼び出すオーバーロードされたメソッド(つまり、メソッドのシグネチャ)の選択は、実行時に動的に決定されません。(オブジェクトタイプではなく)参照タイプによって、呼び出されるオーバーロードされたメソッドが決まります。

public class Car {    
}

public class Toyota extends Car {    
}

public class MyCar {

    public void run(Car c) {
        System.out.println("Run any Car");
    }

    public void run(Toyota t) {
        System.out.println("Run Toyota Car");
    }

    public static void main(String[] args) {
        MyCar myCar = new MyCar();

        Car c1 = new Car();
        myCar.run(c1); // Output: Run any Car

        Toyota c2 = new Toyota();
        myCar.run(c2); // Output: Run Toyota Car

        Car c3 = new Toyota();
        myCar.run(c3); // Output: Run any Car    
    }
}

だから、あなたの場合

Element obj1 = new Label();
Dispatcher.createEditor(obj); // Method with Element argument is called 
                              // as you are passing Element 

Label obj2 = new Label();
Dispatcher.createEditor(obj); // Method with Label argument is called 
                              // as you are passing Label

また、オーバーライドされたメソッド呼び出しは実行時に発生し、オブジェクトタイプ(つまり、ヒープ上の実際のインスタンスのタイプ)によって異なります。

于 2011-01-10T22:08:23.727 に答える
0

あなたはおそらくやっているので:

Element element = new Label();

コンパイラによって決定されます。

于 2010-02-14T21:07:41.240 に答える