多态 - 构造相同类型的对象

时间:2016-03-30 15:17:52

标签: java polymorphism

让我们考虑这个例子:

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();
    }
}

2 个答案:

答案 0 :(得分:4)

解决此问题的典型方法是为LeftRightTypeabstract 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(缺少一个更好的名字):

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);
    }
}

请注意,如果您使用的是Java 8,则可以通过使具体类直接在构造函数中返回来压缩这一点。你甚至不再需要抽象方法了。

{{1}}

然后有

{{1}}

答案 1 :(得分: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);
    }
}