超类属性覆盖子类属性

superclass attribute overrides subclass attribute

我有一个包含许多子class的class,但是当将一个子class实例传递给某个应该接收super[=15实例的方法时=],子class的属性被覆盖

例如下面的代码打印0,我应该怎么做才能打印subclass参数值?

class A{
    int cost;
}

class B extends A{
    int cost = 10;
}

class Test{
    public static void main(String[] args){
        B b = new B();
        method4A(b);

    }

    static void method4A(A a){
        System.out.println(a.cost);
    }
}

虽然字段可以在继承中共享,但如果有正确的访问修饰符(即任何不是 private 的东西 - 默认访问将不会跨不同的包工作),它们在编译时解析,相反在运行时解析的方法(后者称为虚拟方法调用)。

ints 默认为 0,并且您传递的是 A 引用类型,因此打印 A.cost0 值.

这里有多种选择:

  • 不要在 B 中声明 cost 并在 B 的构造函数或实例初始化程序等中将 A 中的 cost 值分配给10
  • method4A 中的丑陋、明确的转换,例如System.out.println(((B)a).cost);
  • method4A
  • 中传递 B 引用类型而不是 A
  • 保留两个 cost 变量并在 A returning cost 中声明一个简单的 getter,并在 [=] 中声明 @Override 17=] 具有相同的实现(如果实例实际上是 B,即使在 A 引用上调用它也会 return B 的成本)

您可以像这样使用带有 getter 的方法覆盖:

class A {
    int cost;

    public int getCost() {
        return cost;
    }

}

class B extends A {
    int cost = 10;

    public int getCost() {
        return cost;
    }
}

class Test {
    public static void main(String[] args) {
        B b = new B();
        method4A(b);
    }

    static void method4A(A a) {
        System.out.println(a.getCost());
    }
}

你的问题与覆盖没有任何关系。

在两个 classes(class 和 subclass)中声明两次相同的字段可能是 error-prone。
您真的需要定义两个不同的字段吗? 为什么不在子 class 中重用父 class 的字段或提供对 的访问权限?

当然,在某些特定情况下,定义两个不同的字段是可以接受和可取的,但对于这些情况,通常您使用 private 修饰符来隔离它们。

定义此类行为的一种自然方式是在父级 class 中为 cost 和 getter 以及 setter 提供一个 private 字段。 这样subclass就有办法value/set这个字段了
例如,它可以从其构造函数中为字段赋值:

class A{

    private int cost;

    public void setCost(int cost){
        this.cost = cost;
    }
    public int getCost(){
       return cost;
   }
}

class B extends A{
    public B(){
       this.setCost(10);
    }
}

class Test{
    public static void main(String[] args){
        B b = new B();
        method4A(b);

    }

    static void method4A(A a){
        System.out.println(a.getCost());
    }
}