类设计的最佳实践(子类+重写)

时间:2012-07-09 19:33:10

标签: java class

我想设计类层次结构。超类有一个抽象方法,子类必须重写这个方法,但我的问题是:这个方法使用超类的数据(实例变量)。

我设计了一些风格来解决这个问题:

样式1:使用私有实例变量并在子类中创建其他实例变量

class SuperClass {
    private T data;

    public SuperClass(T data) { /* ... */}

    public abstract void doSomething();
}

class SubClass extends SuperClass {
    private T data; // use another variable

    public SubClass(T data) {
        super(data);
        this.data = data;
    }

    public void doSomething() {
        // use 'data'
        int length = data.getLength(); // for example...
    }
}

样式2:使用受保护的实例变量:

class SuperClass {
    protected T data;

    public SuperClass(T data) { /* ... */}

    public abstract void doSomething();
}

class SubClass extends SuperClass {
    public void doSomething() {
        // use 'data'
        int length = data.getLength(); // for example...
    }
}

样式3:使用私有实例变量和受保护的方法:

class SuperClass {
    private T data;

    public SuperClass(T data) { /* ... */}

    public abstract void doSomething();

    protected T getData() {
        return data;
    }
}

class SubClass extends SuperClass {
    public void doSomething() {
        // use 'data'
        int length = getData.getLength(); // for example...
    }
}

哪个更好?或者有更多解决方案来更好地解决我的问题?

5 个答案:

答案 0 :(得分:9)

第三种方法通常是首选,如果您设计公共子类,则必须使用。超类希望尽可能多地控制其内部结构。

另一方面,如果您正在开发一个全部位于同一个包中的封闭层次结构,或者至少在同一个项目中,则可以选择将var公开为受保护的,如果有任何好处的话

然而,在子类中复制私有var是所有计数的失败。我想不出任何会对任何事情有帮助的情况。

答案 1 :(得分:1)

恕我直言解决方案#1 很差,因为它不必要地复制了引用,导致混淆(甚至不是内存消耗或一致性)

解决方案#2 #3 同样出色。如果您使用data字段final

protected final T data;

解决方案#2 是最好的。

答案 2 :(得分:1)

这取决于具体情况。例如,当构造函数传递您需要的数据时,可以使用第一个解决方案。第二个问题是扩展类可以访问字段本身(并且它们可以更改值)。第三种方法是将数据封装在类中。

  1. 如果您需要更改子类的字段,可以使用方法2;
  2. 如果你有数据作为构造函数的方法1;
  3. 如果您只是需要公开但保留封装的详细信息,请接近3.
  4. 他们不是一回事。

答案 3 :(得分:1)

我是用户版本2,因为它是最简单的。我尽量让数据最终完成。否则,子类可能会在意外时刻更改数据。

但从个人喜好来看,这些方法并没有多大差别。如果一个变化实际上使它们以某种相关的方式变得不同,那么很容易将一个变为另一个。

当然总有可能会有更好的设计(可能没有继承)潜伏在某个地方,但我们无法从所提供的信息中得知。

评论提示更新:

我经常看到的一个例子是:实现某种策略的子类(B扩展A)。在这些情况下,实际将策略对象作为参数传递给A可能更有意义,它会调用B传入参数的方法。

答案 4 :(得分:1)

     
  • Style1: SuperClass.data和SubClass.data是两个不同的变量,因此无法保证它们会引用同一个对象。
  • Style2:这样可以正常工作,但SubClass可以更改SuperClass变量的引用 - 例如。可以将变量设置为null。它不清楚谁 - 哪些类 - 更新变量。
  • Style3:我认为这是最好的方法,因为SuperClass真正封装并控制对成员变量的访问。
    我们还可以将getData()方法设为final,这样设计就不会被误用。