2012-01-10 64 views
6

当超类有一个标记为final的字段时会发生什么,但是一个子类是否覆盖(隐藏?)这个字段? '最后'不会阻止这一点,是吗? 我正在处理的具体示例是一个建筑类,从中可以继承不同类型的建筑物。除了别的以外,每种类型的成本应该是每个子类的最终成本,但是每种类型的建筑物都应该有自己的成本。Java中最终字段的继承?

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

+0

充分利用现场私人。 – 2012-01-10 05:40:49

+0

像成本变化时常对吗?为什么使它最终。我不认为隐藏领域是一个好主意。 – 2012-01-10 05:43:34

回答

11

final关键字,当应用到一个Java类的字段,无关与继承。相反,它表明在构造函数之外,该字段不能被重新分配。

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

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

希望这会有所帮助!

+0

所以你是说在超类中创建受保护的字段,然后在子类构造函数中自动分配不同的值?听起来很合理。 – TheTedinator 2012-01-11 02:10:54

+1

@TheTedinator - 如果您放弃该字段的“final”修饰符,这将起作用。如果该字段是“final”,则不能在子类构造函数中为其分配不同的值。相反,子类构造函数必须将值传递给超类构造函数才能分配(如我在答案中所示)。如果超类没有在其构造函数中赋值,则代码将不会编译;如果子类构造函数试图从超类设置“final”字段的值,那么代码将不会编译。 – 2012-01-11 04:46:49

+0

@templatetypedef“它表示在构造函数之外,该字段不能被重新分配”并不是真的正确:即使在构造函数中,最终字段也不能被重新分配。因为这个子类的构造函数不能像Ted Hopp所说的那样覆盖超类的最后一个字段。 – Sebastian 2015-08-26 06:51:52

3

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

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, ...); 
    } 
} 
1

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

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

过程中的字段可以公之于众,但这是另一个故事...