class A {
static int c = 7;
int a = 0;
public A() {
c = c + 2;
a = c;
}
public int m(int x){
return a * --x;
}
}
class B extends A{
int a = 13;
static int c = 1;
public B(){
c = c*3;
a = c;
}
public int m (int x){
return --a * ++x;
}
public static void main(String[] args) {
A o1 = new A();
A o2 = new B();
B o3 = new B();
System.out.println(o1.a);
System.out.println(o1.m(o1.a));
System.out.println(o1.a);
System.out.println(c);
System.out.println(o2.a);
System.out.println(o2.m(5));
System.out.println(o2.a);
System.out.println(c);
System.out.println(o3.a);
}
}
我知道动态和静态绑定,但我不明白它在这个例子中是如何工作的(覆盖静态字段)。我真的很惊讶为什么o2.m = 12,而o3.a = 9!这些类的c字段是否分开? B构造函数中使用哪些字段?如果我写了A o1 = new B()或B o1 = new B()?请解释它是如何工作的。
答案 0 :(得分:4)
如果我写了A o1 = new B()
或B o1 = new B()
,会有区别吗。
是的,
A o1 = new B(); calls methods of `B` and fields of A.
B o1 = new B(); calls methods of `B` and fields of B.
,即根据引用类型解析字段引用,并根据对象类型解析(动态)方法调用。
答案 1 :(得分:0)
诀窍在于,在您定义它的方式中,B有2个名为a
的成员。考虑一下:
按如下方法向B类添加方法:
public int x() {
return this.a;
}
public int y() {
return super.a;
}
如果你那么做
public static void main(String[] args) {
B b = new B();
System.out.println(b.x());
System.out.println(b.y());
}
输出将是:
3
9
您在B类中对a
的定义不会替换或覆盖A类中的a
:隐藏它。正如您所看到的,您仍然可以通过调用super
来访问它,但它确实会导致无法维护的代码,因此不鼓励。
你应该做些几件事来避免这种不幸事故:
private
,除非你真的有令人信服的理由不这样做。您的示例已经证明,即使protected
访问也可以使事情变得不透明。B
类型,那么您的对象是定义为A
还是B
并不重要。你是否写下这个:
A obj = new B();
obj.getA();
或者这个:
B obj = new B();
obj.getA();
对您的输出无关紧要,因为您的方法调用将始终将getter称为" low"尽可能在类层次结构中,它始终为B
(如果方法可用),因为对象的运行时类型为B
。最后一点实际上是@TheLostMind的要点