超类属性覆盖子类属性

时间:2018-03-29 14:59:41

标签: java subclass superclass

我有一个包含许多子类的类,但是当将子类实例传递给某个应该接收超类实例的方法时,子类的属性会被覆盖。

例如,以下代码打印0.我应该怎么做才能打印子类参数值?

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

3 个答案:

答案 0 :(得分:2)

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

int默认为0,并且您传递了A引荐类型,因此A.cost的值为{{1}打印。

您可以在此处获得一系列选项:

  • 请勿在{{1​​}}中声明0,并在cost的构造函数或实例初始化程序等中B分配cost值。到A
  • B中一个丑陋的,明确的演员表,例如10
  • method4A
  • 中传递System.out.println(((B)a).cost);引荐类型而非B
  • 保留A个变量,并在method4A cost中声明一个简单的getter,并在A中使用相同的实现声明cost(&#39} ;即使在@Override引用上调用,如果实例实际为B),也会返回B的费用

答案 1 :(得分:1)

你可以使用方法覆盖这样的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());
    }
}

答案 2 :(得分:1)

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

在两个类(类和子类)中声明两次相同的字段可能容易出错 你真的需要定义两个不同的领域吗? 为什么不在子类中重用父类的字段或提供访问权限?

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

定义此类行为的一种自然方式是为private提供cost字段,在父类中提供getter和setter。 通过这种方式,子类可以对该字段进行赋值/设置 例如,它可以从其构造函数中对该字段进行值:

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