我怎样才能在专门的子类中坚持DRY的原则?

时间:2014-08-01 18:12:49

标签: 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 ThreeThing(int b) {
        this.a = 3;
        this.b = b;
    }
}

现在,我想为尊重不变性的所有Thing制作一个方法 - 它会返回一个新的Thing,并将{1}添加到b

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

但是,当此方法继承到ThreeThing时,返回的对象仍然是Thing而不是ThreeThing,因此我必须覆盖ThreeThing中的方法}。这不会是一个大问题,但在我的项目中,会有很多专门的Thing,如果行为是打算的,我不想在所有这些方法中覆盖它。是一样的。

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

  • cloneThing制作方法ThreeThing,将字段复制到新实例,然后使用反射来改变私有字段以获得所需的结果。 ThreeThing中唯一需要的方法是clone
  • 只需使用反射来使用新值
  • 实例化getClass()的结果

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

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

你可以只使用克隆而不进行反射。

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

因此,例如,在子类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;
    ....
  }