给定一个类"Bar",扩展类"Foo",实现接口"DeeDum"
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并在初始化块中设置继承的访问器
虽然您可以在上面的块中设置父属性,但它实际上并不为子类创建副本.
它似乎是多个类的非确定性初始化.
因此,如果你有扩展foo和初始化块的Bar和Baz,它们似乎都继承了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,但为什么声明的区别呢?对我来说似乎是"未定义的".
问题是,你的成员重复申报dee
和dum
的Foo
中Bar
隐藏的那些Foo
.Bar
有自己的成员; 那些Foo
永远不会被使用的Bar
.你的意思是什么
public class Bar extends Foo { { dee = "DEE"; dum = "DUM"; } }
您正在使用子类中定义的变量隐藏继承的变量.
public class Bar extends Foo { public Bar() { dee = "DEE"; dum = "DUM"; } }
应该工作得更好.
当你调用时mybar.getDee()
,你正在调用Foo
基类中定义的方法.(该方法是继承的Bar
.否则,你不会被允许首先在Bar
实例变量上调用它.)该方法返回dee
字段的值,但它是dee
在Foo
类中定义的字段- 类所在的类方法本身已定义.编译器在Foo
类中编译方法时解析了对字段的引用.
其他一些答案使用了覆盖这个词,通过声明一个名为dee
in 的字段来定义你所做的Bar
事情,但事实并非如此.您不能覆盖字段,因为字段不是虚拟的.也许你认为他们是.如果存在"虚拟字段"之类的东西,我也可能期望getDee()
返回字段的运行时类的版本(一个Bar
),而不是编译方法时范围内的那个(Foo
' S).但这并不是Java(或C#,或C++,或Delphi,或我所知的任何其他语言)的工作方式.您习惯使用哪种语言?