最好改变父母的字段或覆盖getter?

时间:2015-08-31 09:28:35

标签: java inheritance override

让我们说我有一个Projectile课程,它可以作为我游戏中所有射弹的基础。它包含最大速度,重力系数,弹跳系数等的默认值。

public abstract class Projectile {

    protected float maxSpeed = 100.0f;
    protected float gravityCoefficient = 1.0f;
    protected float bounceCoefficient = 1.0f;
    ...

}

然后我有一堆子类,每个子类都可以选择覆盖其中一些默认值。

这是哪种方法更好?

1。在子构造函数中设置字段值

public class Arrow {

    public Arrow(){
        super();
        maxSpeed = 200.0f;
    }

}

2。让儿童覆盖吸气剂

public class Arrow {

    public float getMaxSpeed(){
        return 200.0f;
    }

}

我倾向于说第一种方法更好,因为这意味着可以直接访问该字段而无需任何额外的函数调用。但是,它确实意味着在对象创建期间将值设置两次,一次由父级设置,一次由子级设置。

我在这里遗漏了什么?或许还有另一种方法吗?

5 个答案:

答案 0 :(得分:4)

直观地说,任何特定射弹的最大速度在其使用寿命期间不太可能发生变化(即使在相同类型的不同实例可以具有不同的最大速度的情况下),因此我赞成最后的领域。我也赞成让它成为最终 - 我很少使用非私有字段,除了真正的常量。

当你有Projectile的某个状态(字段)时,我会避免让getMaxSpeed显示的最大速度与字段不同而产生混淆。

我可能会这样设计:

public abstract class Projectile {
    private final float maxSpeed;

    protected Projectile(float maxSpeed) {
        this.maxSpeed = maxSpeed;
    }

    // Only if you really need this...
    protected Projectile() {
        this(200f);
    }

    public final getMaxSpeed() {
        return maxSpeed;
    }
}

public class Arrow extends Projectile {
    public Arrow() {
        super(100f);
    }
}

重力系数和弹跳系数可以用类似的方式处理 - 或者如果所有这些真正起作用的话,那么特定类型的每个实例的相同值都是相同的。你可以引入一个新类来表示这些常量,它将类型实例的变化状态与常量限制/系数分开 - 每个实例只能对该新类的实例进行最终引用。不幸的是,Java(以及至少一些类似的语言)并不能很好地模拟这种层次结构。这总是令人烦恼:(

答案 1 :(得分:1)

你应该有一个setter并使用它,这就是setter的用途。它将允许您保持字段私密。另一个好处是使用Java Bean约定将允许您使用诸如Apache Commons BeanUtils之类的库来填充和操作对象。您还可以将数据保存在数据库或文件中。

public abstract class Projectile {

    private float maxSpeed = 100.0f;  // default 

    protected void setMaxSpeed(float newSpeed) {
        maxSpeed = newSpeed;
    }
}

public class Arrow extends Projectile {

    public Arrow() {
        super();
        setMaxSpeed(200.0f);  // arrow specific values
    }
}

答案 2 :(得分:0)

第一种方法。在抽象基类中声明一个名为modifyDefaults()的方法。在每个类中实现它并在构造函数中调用,以便每当有人看到抽象类时,可以得出结论,您将修改子类中的默认值。
或者,如果只有少数决定参数,只需将弹丸创作的责任移交给射弹工厂。

答案 3 :(得分:0)

你对第一个答案的倾向应该是。它确实说明了以下内容:

  • 子类有责任创建自己的实例变量(属性)

  • 吸气剂的覆盖虽然在某些视图中听起来不错,但通常不会提供良好的可维护性。构造函数清楚地说明了额外的一组属性默认值,非常干净。

我不确定你的设计,但如果你的超级课程没有自己的状态,那么尝试制作它abstract并且设计完全改变,比我们在那种情况下所讨论的那样(选项) 2可能被视为时间)。

答案 4 :(得分:-1)

对于java,编译器优化和JIT优化对于提高性能非常重要 第二段代码将更容易优化,无需担心额外的操作。