【发布时间】:2010-10-01 00:09:52
【问题描述】:
给定一个类“Bar”,它扩展了实现接口“DeeDum”的类“Foo”
public interface DeeDum {
public String getDee();
public String getDum();
}
public class Foo implements DeeDum {
public String dee = "D";
public String dum;
public String getDee() { return dee; }
public String getDum() { return dum; }
}
public class Bar extends Foo {
public String dee = "DEE";
public String dum = "DUM";
}
为什么这不起作用?
public static Bar mybar = new Bar();
Assert.assertEquals("DEE", mybar.getDee());
Assert.assertEquals("DUM", mybar.getDum());
我得到“D”和空值。换句话说,Bar 不会从 Foo 继承访问器,也不能覆盖属性。以某种方式调用 mybar.getDum() 调用类 Foo 的静态实例并从父类返回静态属性。即使属性在子类中被覆盖!这是否意味着您不能继承任何方法或属性?
我无法绕过它。为什么 Java 不能继承访问器(为什么他们选择了这样一个奇怪的替代方案?)
还是我做错了什么?
实际上,我仍然看到一些奇怪且不确定的东西。如果您有另一个类 'Bar' 扩展 Foo 并在初始化块中设置继承的访问器
虽然您可以在上面的块中设置父属性,但它实际上并没有为子类创建副本。
这似乎是多个类的非确定性初始化。
因此,如果您有 Bar 和 Baz,它们都扩展 foo 并具有初始化块,那么它们似乎都继承了 Bar 设置的值。
public class Bar extends Foo {
{
dee = "dee";
dum = "dum";
}
}
public class Baz extends Foo {
{
dee = "DEE";
dum = "DUM";
}
}
public static Bar bar = new Bar();
public static Baz baz = new Baz();
System.out.println("mybaz: " + mybaz.getDee() + mybaz.getDum()); // DEEDUM
System.out.println("mybar: " + mybar.getDee() + mybar.getDum()); // DEEDUM
但如果它们以不同的顺序实例化,我会得到:
public static Baz baz = new Baz();
public static Bar bar = new Bar();
System.out.println("mybaz: " + mybaz.getDee() + mybaz.getDum()); // deedum
System.out.println("mybar: " + mybar.getDee() + mybar.getDum()); // deedum
如果在基类 Foo 中设置默认值,结果仍然不同。
我想我现在明白了,Bar 和 Baz 中的初始化块实际上是设置 Foo::dee 和 Foo::dum,但是为什么声明的不同呢?对我来说似乎“未定义”。
【问题讨论】:
-
喂食狂潮开始了……
-
又是一个经典案例,“我不知道 X 是如何工作的,所以 X 肯定是完全错误的。”
-
“Java 学校不教 Java。十一点开始录音”。
标签: java inheritance