2010-12-01 9 views
1

私はスーパークラスのShapeを持ち、Triangle、SquareなどのクラスはShapeを拡張しています。私は現在2つの問題があります:Javaのサブクラスへのメソッドの委託

  1. 私の方法Triangle extends Shapeはコンパイルされません。三角形ではなくシェイプを返さなければなりません。
  2. このメソッドを非表示にしたいと思います。 Shapeのスーパークラスからのみ呼び出すことができます。
public class Shape { 
    public static Shape createShapeFromXML(String xml) { 
    String type = parse(xml); 
     if (type.equals("Triangle") { 
     Triangle.createShapeFromXML(xml); 
     } else if (...) { 
     // ... 
    } 
    } 
} 

public class Triangle extends Shape { 
    public static Triangle createShapeFromXML(String xml) { 
    .... 
    } 
} 

public static void main(String[] args) { 
    String xml = ... 
    Shape s = Shape.createShapeFromXML(xml); 
} 

どのように私はこれらの問題を解決することができますか?

答えて

6

なぜスーパークラスに1つの静的メソッドを保持し、適切なShapeサブクラスを返さないようにしますか?三角形はShapeとis-a関係を持っているため、署名は同じままです。

あなたは別のアプローチは、Factoryパターンを用いることであろう

...あなたがしたいアクセス制限を取得するためにスーパークラスのプライベートでの方法を作ることができます。 ShapeFactoryを持つことができます... xml解析を作成することはShapeクラスの関心事ではないため、これは良い考えです。あなたの懸念を分けてください。ウィキペディアのリンクはパターンの説明には優れていますが、もっと簡単な例が必要です。 thisを参照してください。

+1

具体的には、これは抽象ファクトリの例とみなされます。私はGoFが2つの別々のパターンとしてそれらを分類した理由を本当に知りません。 –

+0

工場パターンに+1します。それはシェイプクラスの責任foprオブジェクトの作成 –

+0

@カール:FactoryMethodとAbstractFactoryの基本的な違いは、FactoryMethodがクラス階層(抽象基底クラス)から呼び出され、AbstractFactoryは外部から使用されるということです。 (GoFBookは、FactoryMethodが "クラスベース"であるのに対し、AbstractFactoryは "オブジェクトベース"であると言って、この事実を暗示しようとしています) - JavaRanch FAQから。 –

1

コードをコンパイルするには、public static Shape createShapeFromXML(String xml)をTriangleクラスで宣言する必要があります。

 

public class Shape { 

    public static void main(String[] args) { 
      String xml = "Triangle"; 
      Shape s = Shape.createShapeFromXML(xml); 
      System.out.println(s.toString()); 
    } 

    public static Shape createShapeFromXML(String xml) { 
     Shape aShape = null; 

     if (xml.equals("Triangle")) { 
     aShape = Triangle.createShapeFromXML(xml); 
     } 
     return aShape; 
    } 
} 

class Triangle extends Shape { 

    public static Shape createShapeFromXML(String xml) { 
     return new Triangle(); 
    } 

    @Override 
    public String toString() { 
     return "Triangle"; 
    } 
} 

 

System.out.println(s.toString());メインメソッド出力では "Triangle"が出力され、これは三角形が作成されていることを示しています。

2

// 2. I want to hide this method. It should only be callable from superclass Shape

実装をロックダウンするために、シェイプメソッドfinalを作成できます。サブクラス型(例ではTriangle)を返すオーバーロードされたメソッドであっても、コンパイラによってフラグが立てられます。

public static final Shape createShapeFromXML(String xml) { ... } 

編集:コメント欄での会話に応じて

は、証拠のために私は次のことを提供します。

上記のコンパイルエラーになりますをコンパイルしようと
public class Shape { 
    public static final Shape createShapeFromXML(String xml) { 
     if (xml.equals("Triangle")) {//removed parse for demo compliation 
     return Triangle.createShapeFromXML(xml); 
     } else { 
     return new Shape(); 
     } 
    } 
} 

public class Triangle extends Shape{ 
    public static Triangle createShapeFromXML(String xml) { 
     return new Triangle(); 
    } 
} 

mybox:src akf$ javac Triangle.java 
Triangle.java:3: createShapeFromXML(java.lang.String) in Triangle cannot override createShapeFromXML(java.lang.String) in Shape; overridden method is static final 
    public static Triangle createShapeFromXML(String xml) { 
           ^
1 error 

このことは、JLSを参照して説明することができます2節:

If a class declares a static method, then the declaration of that method is said to hide any and all methods with the same signature in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class.

、その後8.4.3.3 final方法から:

(クラスメソッドによって)8.4.6.2非表示から

A method can be declared final to prevent subclasses from overriding or hiding it. It is a compile-time error to attempt to override or hide a final method.

一緒に2を入れて、静的メソッドのシグネチャにfinalを追加すると、そのメソッドがサブクラスによって隠されないように保護されます。コンパイル時のチェックが強制されます。

+0

静的メソッドはオーバーライドできないので、 'final'は文字通り何もしません。 – ColinD

+0

これは正当なものであり、おそらく「隠されている」よりも優先される用語が優先されます。 'final'は、同じシグネチャを持つメソッドをサブクラスで実装することを禁止するので、コンパイラはメソッド隠蔽のフラグを立てます。 – akf

+0

@afk:それは実際にはありません。 – ColinD

関連する問題