2016-03-30 9 views
2

のオブジェクトを構築:ポリモーフィズム - さんは、この例を考えてみましょう同じタイプ

class InheritedType extends Type { 

    public Type simplify() { 
     Type newLeft = left.simplify(); 
     Type newRight = right.simplify(); 
     Type newExpr = new InheritedType(newLeft, newRight); 
     return newExpr.simplify(); 
    } 
} 

は今、私はこの方法では、ちょうど同じ、唯一のコンストラクタ名で別の継承タイプ

class InheritedType2 extends Type { 

    public Type simplify() { 
     Type newLeft = left.simplify(); 
     Type newRight = right.simplify(); 
     Type newExpr = new InheritedType2(newLeft, newRight); 
     return newExpr.simplify(); 
    } 
} 

を作成したいです異なる。コードの重複を避ける方法はありますか?次のコードは動作しません

class Type { 

    public Type simplify() { 
     Type newLeft = left.simplify(); 
     Type newRight = right.simplify(); 
     Type newExpr = new this(newLeft, newRight); 
     return newExpr.simplify(); 
    } 
} 
+0

は、あなたのコードは、本当に意味がありませんしています。 'simplify'へのすべての呼び出しは' simplify'への再帰呼び出しで終わります。あなたのメソッドは、宣言されていないフィールドを参照するので、宣言する場所を明確にしていません。便利なアドバイスが必要な場合は、最小*正しい例を投稿してください。 – ruakh

答えて

4

この問題を回避する一般的な方法はInheritedTypeInheritedType2のための共通のスーパークラスを導入することです。明らかに、これらの2つのタイプはロジックを共有しています。主に、左右のオペランドの両方で動作します。だから、私たちは(より良い名前の不足のため)LeftRightTypeを作成してみましょう:

abstract class LeftRightType extends Type { 

    private Type left, right; 

    public LeftRightType(Type left, Type right) { 
     this.left = left; 
     this.right = right; 
    } 

    @Override 
    public Type simplify() { 
     return newInstance(left.simplify(), right.simplify()).simplify(); 
    } 

    public abstract Type newInstance(Type left, Type right); 

} 

それはあなたが現在複製して実装が上書きされますnewInstance抽象メソッドに具体的なインスタンスの作成を委任されているロジックを保持しています。そして、あなたは単にあなたは、Java 8を使用している場合、あなたは、コンストラクタに直接返すように具体的なクラスを与えることによって、その多くを凝縮できること

class InheritedType extends LeftRightType { 
    public InheritedType(Type left, Type right) { 
     super(left, right); 
    } 
    @Override 
    public Type newInstance(Type left, Type right) { 
     return new InheritedType(left, right); 
    } 
} 

class InheritedType2 extends LeftRightType { 
    public InheritedType2(Type left, Type right) { 
     super(left, right); 
    } 
    @Override 
    public Type newInstance(Type left, Type right) { 
     return new InheritedType2(left, right); 
    } 
} 

注意を持つことができます。もはや抽象メソッドは必要ありません。

abstract class LeftRightType extends Type { 

    private Type left, right; 
    private BinaryOperator<Type> typeSupplier; 

    public LeftRightType(Type left, Type right, BinaryOperator<Type> typeSupplier) { 
     this.left = left; 
     this.right = right; 
     this.typeSupplier = typeSupplier; 
    } 

    public Type simplify() { 
     return typeSupplier.apply(left.simplify(), right.simplify()).simplify(); 
    } 
} 

、その後

class InheritedType extends LeftRightType { 
    public InheritedType(Type left, Type right) { 
     super(left, right, InheritedType::new); 
    } 
} 

class InheritedType2 extends LeftRightType { 
    public InheritedType2(Type left, Type right) { 
     super(left, right, InheritedType2::new); 
    } 
} 
2

ができませ「不思議の定期的なテンプレートパターン」https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

abstract class Type<This extends Type<This>> { 
    protected abstract This newInstance(Type<?> newLeft, Type<?> newRight); 

    public This simplify() { 
     Type<?> newLeft = left.simplify(); 
     Type<?> newRight = right.simplify(); 
     This newExpr = newInstance(newLeft, newRight); 
     return newExpr.simplify(); 
    } 
} 

class InheritedType extends Type<InheritedType> { 
    protected InheritedType newInstance(Type<?> left, Type<?> right) { 
     new InheritedType(left, right); 
    } 
} 

class InheritedType2 extends Type<InheritedType2> { 
    protected InheritedType2 newInstance(Type<?> left, Type<?> right) { 
     new InheritedType2(left, right); 
    } 
} 
関連する問題