给定一个类"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";
}
Run Code Online (Sandbox Code Playgroud)
为什么这不起作用?
public static Bar mybar = new Bar();
Assert.assertEquals("DEE", mybar.getDee());
Assert.assertEquals("DUM", mybar.getDum());
Run Code Online (Sandbox Code Playgroud)
我得到"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
Run Code Online (Sandbox Code Playgroud)
但如果他们以不同的顺序实例化,我得到:
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
Run Code Online (Sandbox Code Playgroud)
如果在基类Foo中设置了默认值,它仍然会有所不同.
我想我现在明白Bar和Baz中的初始化块实际上是设置Foo :: dee和Foo :: dum,但为什么声明的区别呢?对我来说似乎是"未定义的".
Arn*_*ter 13
问题是,你的成员重复申报dee和dum的Foo中Bar隐藏的那些Foo.Bar有自己的成员; 那些Foo永远不会被使用的Bar.你的意思是什么
public class Bar extends Foo {
{
dee = "DEE";
dum = "DUM";
}
}
Run Code Online (Sandbox Code Playgroud)
您正在使用子类中定义的变量隐藏继承的变量.
public class Bar extends Foo {
public Bar() {
dee = "DEE";
dum = "DUM";
}
}
Run Code Online (Sandbox Code Playgroud)
应该工作得更好.
当你调用时mybar.getDee(),你正在调用Foo基类中定义的方法.(该方法是继承的Bar.否则,你不会被允许首先在Bar实例变量上调用它.)该方法返回dee字段的值,但它是dee在Foo类中定义的字段- 类所在的类方法本身已定义.编译器在Foo类中编译方法时解析了对字段的引用.
其他一些答案使用了覆盖这个词,通过声明一个名为deein 的字段来定义你所做的Bar事情,但事实并非如此.您不能覆盖字段,因为字段不是虚拟的.也许你认为他们是.如果存在"虚拟字段"之类的东西,我也可能期望getDee()返回字段的运行时类的版本(一个Bar),而不是编译方法时范围内的那个(Foo' S).但这并不是Java(或C#,或C++,或Delphi,或我所知的任何其他语言)的工作方式.您习惯使用哪种语言?
| 归档时间: |
|
| 查看次数: |
1397 次 |
| 最近记录: |