简体   繁体   English

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

[英]How can I uphold the principle of DRY in a specialized subclass?

I want to make a class with N fields, then subclass it with N-1 fields, and in the subclass the first field should be filled in the constructor. 我想创建一个具有N个字段的类,然后使用N-1个字段将其子类化,并且在子类中,应该在构造函数中填充第一个字段。 Here's the simplest example: 这是最简单的例子:

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

Now, I want to make a method for all Thing s that respects immutability- it returns a new Thing with 1 added to b . 现在,我想为尊重不变性的所有Thing制作一个方法 - 它返回一个新的Thing其中1添加到b

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

However, when this method is inherited into ThreeThing , the returned object is still a Thing instead of ThreeThing , so I'd have to override the method in ThreeThing . 但是,当此方法继承到ThreeThing ,返回的对象仍然是Thing而不是ThreeThing ,因此我必须覆盖ThreeThing的方法。 This wouldn't be a big problem, but in my project, there are going to be lots of specialized Thing s and I don't want to have to override the method in all of them if the behavior is intended to be the same. 这不会是一个大问题,但在我的项目中,会有很多专门的Thing ,如果行为是相同的话,我不想在所有这些中覆盖方法。

Here are the possible solutions I have thought of, none of them satisfy me 以下是我想到的可能的解决方案,他们都没有满足我

  • Make a method clone for Thing and ThreeThing that copies over the fields to a new instance, then use reflection to mutate the private fields to obtain the desired result. ThingThreeThing创建方法clone ,将字段复制到新实例,然后使用反射来改变私有字段以获得所需的结果。 The only method that would be needed in ThreeThing is clone . ThreeThing唯一需要的ThreeThingclone
  • Simply use reflection to instantiate the result of getClass() with the new values 只需使用反射来使用新值实例化getClass()的结果

Is there a way to do this without reflection or a better way to design the objects? 有没有办法在没有反射或更好的方式设计对象的情况下做到这一点?

Since the parent can't instantiate the child directly (because it doesn't "know" it) you can use reflection to do it: 由于父级无法直接实例化子级(因为它不“知道”它),您可以使用反射来执行此操作:

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

That said, it's better to avoid using newInstance() and if you find yourself using it - you might want to back up a few steps and check the overall design and see if it can be improved. 也就是说, 最好避免使用newInstance() ,如果你发现自己正在使用它 - 你可能需要备份几个步骤并检查整体设计,看看它是否可以改进。 As an example, I added a copy() method which should be overridden in the child classes. 作为一个例子,我添加了一个copy()方法,应该在子类中重写。

You can do it with just clone and no reflection. 你可以用克隆而不用反射来做到这一点。

Each non-abstract class of your hierarchy with have a clone method that creates an instance and passes it to another clone method that clones the members. 层次结构的每个非抽象类都有一个克隆方法,该方法创建一个实例并将其传递给另一个克隆成员的克隆方法。 Abstract classes in the hierarchy would only have the protected method that only clones the members. 层次结构中的抽象类只有受保护的方法才能克隆成员。

So, for example, in the sub-class ThreeThing you will have : 因此,例如,在子类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;
    ....
  }

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

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