3

簡単に言えば、次のコードで「sub」を出力する必要があります。

Element e = new SubElement();
print(e);
... 

private static void print(Element e) {
    System.out.println("e");
}

private static void print(SubElement e) {
    System.out.println("sub");
}

そして私はprint(要素e)を変更したくありません。だから何も好きではない

private static void print(Element e) {
    if (e instanceof SubElement) {
        print((SubElement) e);
    } else {
        System.out.println("e");
    }
}

私がやりたいのは

print(e.getClass().cast(e));

それを実際のサブクラスに自動的にキャストし、システムにprint(SubElement e)を強制的に入力させます。これはどういうわけか可能ですか?

4

5 に答える 5

7

実行されるオーバーロードされたメソッドはコンパイル時に選択されるため、SubElementバージョンではなくElementバージョンが選択されます。より論理的に見えるのは、Elementまたはサブクラスに印刷する必要のあるデータを含めることです。

class Element {

    public String getName() {
        return "e";
    }
}

class SubElement extends Element {
    public String getName() {
        return "sub";
    }
}

次に、printメソッドで:

private static void print(Element e) {
    System.out.println(e.getName());
}

これが意味をなすかどうかは、Elementクラスが実際に何であるか、および印刷されたデータが何を表すかによって異なります。

于 2010-08-26T10:28:41.177 に答える
1

はい。ビジターパターンを使用できます。ただし、定義する必要のあるビジターインターフェイスにはタイプごとのメソッドが必要なため、明確に定義された階層を確立するのに適しています。

interface ElementVisitor {
   visit(Element e);
   visit(SubElement se);
}

class ElementerPrinter implements ElementVisitor {
   visit(Element e) { System.out.println("e"); }
   visit(SubElement e) { System.out.println("sub"); }
}

class Element {
  // here's the trick, Element knows that this is Element
  // and childs have to implement it!
  // if the parent-most class is an interface it force you to implement!
  accept(ElementVisitor visitor) { visitor.visit(this); } 
}

class SubElement {
  // here's the trick, Element knows that this is SubElement
  accept(ElementVisitor visitor) { visitor.visit(this); }
}
于 2010-08-26T10:16:52.343 に答える
1

print()Element本当にのインスタンスメソッドになる必要があります。そうでなければ、あなたは難しい方法でポリモーフィズムを模倣しようとしています。これを実行したい場合は、関数オブジェクトifからのマッピングの一連のステートメントを実際に回避することはできません。Classなぜわざわざ?

于 2010-08-26T10:17:20.220 に答える
0

別のアプローチを選択します。また

  1. 他の人が提案しているようにポリモーフィズムを使用し、Elementを拡張してprint()メソッド(サブクラスで上書き可能)を追加するか、
  2. ヘルパーインターフェイスを定義し、戦略とファクトリパターンの組み合わせを使用します。

基本クラス

 public class Element{}

派生クラス

 public class SubElement extends Element{}

要素を印刷するためのヘルパーインターフェイス

public interface PrintHelper{
    void print(Element element);
}

特定の要素に最適なPrintHelperを取得するためのファクトリ

public class PrintHelperFactory{

    private final Map<Class<? extends Element>, PrintHelper> registeredHelpers =
        new HashMap<Class<? extends Element>, PrintHelper>();

    // Register a PrintHelper for a given Element class.
    public void registerHelper(final Class<? extends Element> clazz,
      final PrintHelper helper){
        this.registeredHelpers.put(clazz, helper);
    }

    // Get the most specific PrintHelper for a given Element.
    public PrintHelper getHelperForElement(final Element element){
        Class<? extends Element> clazz = element.getClass();
        while(!Object.class.equals(clazz)){
            if(this.registeredHelpers.containsKey(clazz)){
                return this.registeredHelpers.get(clazz);
            }
            clazz = (Class<? extends Element>) clazz.getSuperclass();
        }
        return null;
    }

}

クライアントテストクラス、Javaアプリケーションとして実行

public class Main{

    public static void main(final String[] args){

        final PrintHelperFactory factory = new PrintHelperFactory();
        factory.registerHelper(Element.class, new PrintHelper(){
            @Override
            public void print(final Element element){
                System.out.println("Element");
            }
        });
        factory.registerHelper(SubElement.class, new PrintHelper(){
            @Override
            public void print(final Element element){
                System.out.println("Sub Element");
            }
        });

        // test it with an Element  
        final Element elem = new Element();
        factory.getHelperForElement(elem).print(elem);

        // test it with a sub class
        final Element sub = new SubElement();
        factory.getHelperForElement(sub).print(sub);

    }

}

出力

Element
Sub Element
于 2010-08-26T10:35:17.337 に答える
0

動作の違いを要素クラスにプッシュできますか?

Element e = new SubElement();
print(e);
... 

private static void print(Element e) {
    System.out.println(e.getMessageToPrint());
}

// no longer needed
//
//private static void print(SubElement e) {
//    System.out.println("sub");
//}

このようにして、メソッドSubElementをオーバーライドできます。getMessageToPrint()

またはさらに良い:

Element e = new SubElement();
e.print();
于 2010-08-26T10:29:01.993 に答える