Java 如何在一个专门的子类中坚持DRY的原则?

Java 如何在一个专门的子类中坚持DRY的原则?,java,oop,Java,Oop,我想用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 ThreeT

我想用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;
    }
}
现在,我想为所有尊重不变性的
Thing
s创建一个方法-它返回一个新的
Thing
,并在
b
中添加1

public Thing transform() {
    return new Thing(this.a, this.b + 1);
}
但是,当此方法被继承到
ThreeThing
中时,返回的对象仍然是
Thing
而不是
ThreeThing
,因此我必须重写
ThreeThing
中的方法。这不是什么大问题,但在我的项目中,会有很多专门的
东西
s,如果行为是相同的,我不想覆盖所有这些方法

以下是我想到的可能的解决方案,没有一个能让我满意

  • Thing
    ThreeThing
    创建一个方法
    clone
    ,将字段复制到一个新实例,然后使用反射来改变私有字段以获得所需的结果。
    ThreeThing
    中唯一需要的方法是
    clone
  • 只需使用反射就可以用新值实例化
    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()
,如果您发现自己正在使用它,您可能需要备份一些步骤,检查总体设计,看看是否可以改进。例如,我添加了一个
copy()
方法,该方法应该在子类中被重写。

您可以只使用克隆而不使用反射

具有的层次结构中的每个非抽象类都有一个克隆方法,该方法创建一个实例并将其传递给另一个克隆成员的克隆方法。层次结构中的抽象类将只有仅克隆成员的受保护方法

例如,在子类
ThreeThing
中,您将有:

  public Object clone ()
  {
    ThreeThing 
      thing = new ThreeThing ();

    clone (thing);

    return thing;
  }

  protected void clone (Thing other)
  {
    super.clone (other);

    ThreeThing 
      thing = (ThreeThing) other;
    thing.some_member = this.some_member;
    ....
  }

记住实现
Cloneable
@whowantsakookie我同意,我只是没有包含完整的类定义。(应该避免)当
某个\u成员
是一个私有字段时,这怎么可能起作用?@itdoesnwork它起作用,因为您是从引入它的同一类访问私有字段的
clone
of
ThreeThing
只克隆
ThreeThing
引入的成员,
clone
of
Thing
只克隆
Thing
引入的成员,等等……这几乎是我的总体设计。您有什么改进的建议吗?在我看来,在子类中实现
transform()
,或者在每个子类中创建一个
copy()
,并在
transform
中使用它会更有意义