この問題を回避する一般的な方法はInheritedType
とInheritedType2
のための共通のスーパークラスを導入することです。明らかに、これらの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);
}
}
は、あなたのコードは、本当に意味がありませんしています。 'simplify'へのすべての呼び出しは' simplify'への再帰呼び出しで終わります。あなたのメソッドは、宣言されていないフィールドを参照するので、宣言する場所を明確にしていません。便利なアドバイスが必要な場合は、最小*正しい例を投稿してください。 – ruakh