简体   繁体   English

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

[英]Polymorphism - construct an object of the same type

Let's consider this example: 让我们考虑这个例子:

class InheritedType extends Type {

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

Now I'd create another inherited type 现在,我将创建另一个继承的类型

class InheritedType2 extends Type {

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

This method is just the same, only the constructor name differs. 此方法是相同的,只是构造函数名称不同。 Is there any way to avoid code duplication? 有什么办法可以避免代码重复? The following code doesn't work 以下代码不起作用

class Type {

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

The typical way around this problem is to introduce a common superclass for InheritedType and InheritedType2 . 解决此问题的典型方法是为InheritedTypeInheritedType2引入一个公共超类。 This is because, clearly, those two types share logic, mainly: they operate both on left and right operands. 显然,这是因为这两种类型共享逻辑,主要是:它们在左和右操作数上操作。 So let us create a LeftRightType (for lack of a better name): 因此,让我们创建一个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);

}

It holds the logic you are currently duplicating and delegate the creation of the concrete instance into a newInstance abstract method that implementors will override. 它包含您当前正在复制的逻辑,并将具体实例的创建委派给实现者将覆盖的newInstance抽象方法。 Then you can simply have 然后,您可以简单地拥有

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

Note that if you're using Java 8, you can condense that a lot by giving the concrete class to return directly in the constructor. 请注意,如果您使用的是Java 8,则可以通过提供具体类以直接在构造函数中返回的方式来简化很多内容。 You don't even need an abstract method anymore. 您甚至不再需要抽象方法。

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

and then have 然后有

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

You can you "curiously recurring template pattern" https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern : 您可以“好奇地重复使用模板模式” 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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM