【问题标题】:Inheritance of final fields in Java?Java中最终字段的继承?
【发布时间】:2012-02-06 14:43:20
【问题描述】:

当超类有一个标记为 final 的字段,但子类覆盖(隐藏?)该字段时会发生什么? “决赛”并没有阻止这一切,不是吗? 我正在研究的具体示例是 Building 类,不同类型的建筑物都从该类继承。除其他事项外,每种类型的成本应该是每个子类的最终成本,但每种类型的建筑都应该有自己的成本。

编辑:我已经意识到我不知道我在上面说的是什么。我真正想要的是成本的静态变量。但是,如果我在超类中声明这些静态变量,它们对于超类来说是静态的,因此 Subclass1.cost,例如,指的是与 Superclass.cost 或 Subclass2.cost 相同的值。如何使变量对每个子类都是静态的,而不必在每个类中声明它们。

【问题讨论】:

  • 诸如成本之类的东西会不时变化,对吧?为什么要最终确定。我不认为隐藏字段是个好主意。

标签: java inheritance static


【解决方案1】:

final 关键字在应用于 Java 类的字段时,与继承无关。相反,它表示在构造函数之外,不能重新分配该字段。

Java 分别处理名称隐藏和覆盖。覆盖实际上通过切换调用哪个函数来改变程序在运行时的可观察行为,而名称隐藏通过改变引用哪个字段的静态解释来改变程序。 final 应用于覆盖仅适用于方法,因为 Java 中的字段不能被覆盖。不幸的是,在这些不同的上下文中使用final 有点令人困惑,并且没有办法防止字段将其名称隐藏在子类中。

如果您希望建筑物具有不同的成本,一种选择是覆盖getCost 方法,该方法在每个派生类中被不同地覆盖。或者,您可以在存储成本的基类中有一个 protected 或 private 字段,然后让每个子类直接设置此字段(如果这是 protected)或通过基类构造函数(如果这字段为private)。

希望这会有所帮助!

【讨论】:

  • 所以你是说在超类中创建受保护的字段,然后在子类构造函数中自动分配不同的值?听起来很合理。
  • @TheTedinator - 如果您放弃该字段的 final 修饰符,这将起作用。如果该字段为final,则不能在子类构造函数中为其分配不同的值。相反,子类构造函数必须将值传递给要分配的超类构造函数(如我在回答中所示)。如果超类没有在其构造函数中赋值,代码将无法编译;如果子类构造函数尝试从超类中设置final 字段的值,则代码将无法编译。
  • @templatetypedef “它表示在构造函数之外,该字段不能被重新分配”并不正确:即使在构造函数中,也不能重新分配最终字段。因此,正如 Ted Hopp 所说,子类构造函数不能覆盖超类中的 final 字段。
【解决方案2】:

您可以通过两种方式做到这一点:创建一个访问函数并隐藏字段本身,或者将构建成本从子类传递给超类构造函数。您可以将这些组合起来并创建一个不能被子类覆盖的属性:

public class Building {
    private final int cost;

    protected Building(int cost, ...) {
        this.cost = cost;
    }

    public final int getCost() {
        return cost;
    }
}

public class Cottage extends Building {
    public Cottage() {
        super(COTTAGE_COST, ...);
    }
}

【讨论】:

    【解决方案3】:

    同意其他答案,但我认为在这种情况下以下实现更好:

        public abstract class Building {
    
            private final int cost;
    
            public Building(int cost) {
                this.cost = cost;
            }
    
            public final int getCost() {
                return cost;
            }
        }
    
        class Skyscraper extends Building {
            public Skyscraper() {
                super(100500);
            }
        }
    

    当然可以公开该领域,但那是另一回事了...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-28
      • 2013-01-09
      • 2017-09-20
      • 1970-01-01
      • 1970-01-01
      • 2018-04-10
      • 1970-01-01
      相关资源
      最近更新 更多