java – 我如何在专门的子类中坚持DRY的原则?

我想创建一个具有N个字段的类,然后使用N-1个字段将其子类化,并且在子类中,应该在构造函数中填充第一个字段.这是最简单的例子:

class Thing {
    protected int a;
    protected int b;

    public Thing(int a, int b) {
        this.a = a;
        this.b = b;
    }
}

class ThreeThing extends Thing {
    public ThreeThing(int b) {
        this.a = 3;
        this.b = b;
    }
}

现在,我想为所有尊重不变性的东西制作一个方法 – 它返回一个新的东西,其中1添加到b.

public Thing transform() {
    return new Thing(this.a, this.b + 1);
}

但是,当此方法继承到ThreeThing时,返回的对象仍然是Thing而不是ThreeThing,因此我必须覆盖ThreeThing中的方法.这不是一个大问题,但在我的项目中,会有很多专门的东西,如果行为是相同的话,我不想在所有这些方法中覆盖该方法.

以下是我想到的可能的解决方案,他们都没有满足我

>为Thing和ThreeThing创建方法克隆,将字段复制到新实例,然后使用反射来改变私有字段以获得所需的结果. ThreeThing中唯一需要的方法是克隆.
>只需使用反射来使用新值实例化getClass()的结果

有没有办法在没有反射或更好的方式设计对象的情况下做到这一点?

最佳答案 由于父级无法直接实例化子级(因为它不“知道”它),您可以使用反射来执行此操作:

class Thing {
    protected int a;
    protected int b;

    public void setB(int b) {
        this.b = b;
    }

    public void setA(int a) {
        this.a = a;
    }

    public Thing(){}

    public Thing(int a, int b) {
        this.a = a;
        this.b = b;
    }

    Thing copy() {                  // adding a copy method
        return new Thing(a, b);
    }

    public Thing transform() throws IllegalAccessException, InstantiationException {
        // Thing result = (Thing)this.getClass().newInstance(); // one way to do it (reflection)
        Thing result = copy(); // a better way to do it
        result.setA(a);
        result.setB(b+1);
        return result;
    }

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        ThreeThing x = new ThreeThing(1);
        System.out.println(x.a + " : " + x.b);
        Thing y = x.transform();
        System.out.println(y.a + " : " + y.b);
    }
}

class ThreeThing extends Thing {

    public ThreeThing(){}

    ThreeThing(int b) {
        this.a = 3;
        this.b = b;
    }

    @Override
    Thing copy() {           // adding a copy method
        return new ThreeThing(b);
    }
}

也就是说,使用newInstance()是better to avoid,如果你发现自己正在使用它 – 你可能需要备份几个步骤并检查整体设计,看看是否可以改进.作为一个例子,我添加了一个copy()方法,应该在子类中重写.

点赞