子类在Java中使用哪些数据成员?

时间:2016-01-23 13:55:22

标签: java inheritance override function-overriding

public class HelloWorld{

     public static void main(String []args){
        Ball b=new Ball();
        System.out.println(b.getName());
     }
}

class Shape{
    private String name;
    Shape(){
        name="Shape";
    }
    public String getName(){
        return name;
    }
}

class Ball extends Shape{
    private String name;
    public Ball(){
        name="Ball";
    }
}

为什么我输出为:" Shape"而不是" Ball"?

即使我改变了

,我也会得到相同的结果
private String name;

public String name;

ShapeBall类中。

4 个答案:

答案 0 :(得分:3)

Ball对象中有两个name字段 - 一个在Ball类中定义,另一个在Shape类中定义。

在子类中创建具有相同名称的字段时,您需要hide父类字段。尽量避免在代码中使用它。通常,您仍然可以使用超级关键字(例如super.name)访问父字段,但由于您的字段是私密的,因此无法执行此操作。

方法Shape#getName从其类中返回字段name。 Java中的字段不会覆盖像方法那样的父字段,因此Shape.name不会被Ball.name替换。

查看此代码以了解参考类型如何确定要使用的字段

Ball ball = new Ball();
println ball.name;  // prints Ball, because reference type if Ball

Shape shape = ball; // this is same ball object
println shape.name; // prints Shape, because reference type is Shape

println ball.getName(); // prints Shape - getter in Shape class can only see Shape fields

如果你在Ball课程中添加了getter,那么方法调用将始终返回' Ball'

println ball.getName();  // will print Ball
println shape.getName(); // will print Ball

答案 1 :(得分:1)

对于字段,没有神奇的覆盖名称。如果类中有一个字段,而子类中有一个同名字段,则有两个不同的字段。

Shape.nameBall.name是完全独立的实体。如果您设置了两个字段public,则会获得:

Shape s = new Ball();
s.getName();   // => returns "shape"
s.name         // yields "shape", because you are accessing a class of type `Shape`.
((Ball)s).name // yields "ball", because you are accessing a class of type `Ball`

此时Ball实际上有两个不同的name字段:从Shape继承的字段和在Ball类本身中声明的字段。

但是,如果您在name内访问Ball,则会获得第一个由符号查找规则确定的Ball.name。如果Shape.nameprotectedpublic,则super.name可以使用Shape。请再次注意:有两个单独的名称字段,每个类一个。它们碰巧具有相同的字段名称,但在其他方面完全分开。

相同的查找规则也适用于Shape.getName():编译name时,它会尝试在编译时找到名为Shape 的字段并使用找到一个,这是目前唯一可用的一个:Shape.name中的一个。查找是静态的。

但是,如果Ball是私有的,则无法直接从computed_val = ... constant_val = tf.constant(37.0) pred = tf.less(computed_val, constant_val) # N.B. Types of the two args must match 类访问它。

答案 2 :(得分:0)

在Java中,所有继承都从超类传递到子类,包括实例变量和方法。

意思是,如果你想用“子类参数”“调用超类方法”,你只需在子类中创建一个对象并调用你的方法。

因为名为getName()的唯一方法位于你的超类中,所以当调用方法getName()时,首先在子类中搜索子类,而不是它在超类中搜索。
为此,您有:Shape而不是Ball

答案 3 :(得分:0)

当你创建新球时,在球构造函数中,隐式执行的第一件事是超级构造函数,没有参数。这意味着执行形状构造函数设置name =" shape"。然后,由于getName方法没有重载,你得到了"形状"值。