是否可以在Java中覆盖类参数?我很确定这是不可能的,但是...
public class Dad {
protected Building home;
public Dad() {
}
public Building getHome(){
return this.home;
}
}
public class Son extends Dad {
protected Shack home;
public Son () {
super();
this.home = new Shack();
}
}
public Shack extends Building{
(...)
}
显然,添加两个具有相同名称的参数没有问题,但是我不确定两个参数是否“链接”在一起。
当我从getHome()
对象调用Son
函数时,它返回一个空对象。这很有意义,因为Dad
对象没有初始化的Building
对象。即使Son
具有初始化Shack
类的初始化Building
对象。 (我不知道我是否足够清楚...)
一个简单的解决方案是简单地使用home
对象初始化Shack
并在需要时将home
投射到Shack
中。但我想知道是否还有另一种方法可以做到这一点。
答案 0 :(得分:1)
不能覆盖字段。在您儿子的情况下,爸爸的hiding字段是:
在一个类中,与该字段中的字段同名的字段 超类隐藏超类的字段,即使它们的类型是 不同。在子类中,超类中的字段不能为 以其简单名称引用。 [...]一般 讲,我们不建议隐藏字段,因为这会使代码变得困难 阅读。
已在GetHome
类中声明了Dad
函数,因此它只能看到home
实例形式Dad
,该实例为空。您可以从Son实例以home
的身份访问爸爸的super.home
。
您可以提取超类或接口。
interface HasHome {
Building getHome();
}
class Dad implements HasHome {
protected Building home;
public Dad() {
this.home = new Building();
}
@Override
public Building getHome(){
return this.home;
}
}
class Son implements HasHome { // Or extends Dad
protected Shack home;
public Son () {
super();
this.home = new Shack();
}
@Override
public Shack getHome() {
return home;
}
}
有another question种选择方式。而且,超类型可以是通用的,如@Lorelorelore所示。
答案 1 :(得分:1)
您不应在子类中重新声明具有相同名称的字段。这是因为字段是隐藏的,而不是被覆盖。
编译器不会对此抱怨,但是在这种情况下有两个变量。 Dad.home
中的构造方法未分配Son
。因此,在此示例中,new Son().getHome()
将返回null
,这是因为getHome()
只知道Dad.home
。
在您所处的位置,最好的办法就是从home
中删除Son
属性,更好的是,在private
中将其设为Dad
,并从子类使用构造函数参数。
答案 2 :(得分:1)
也许您应该使用泛型来重构这两个类:
抽象超类:
public abstract class Person<T extends Building> {
protected T home;
public T getHome(){
return this.home;
}
}
爸爸班:
public class Dad extends Person<Building> {
public Dad() {
home = new Building();
}
}
儿子班:
public class Son extends Person<Shack> {
public Son () {
home = new Shack();
}
}
您可以通过简单的测试来检查home
字段的类型是否正确(并且也不为null):
public class SonAndDadTest {
@Test
public void sonTest(){
Son son = new Son();
Assert.assertNotNull(son.getHome());
Assert.assertEquals(son.getHome().getClass(), Shack.class);
}
@Test
public void dadTest(){
Dad dad = new Dad();
Assert.assertNotNull(dad.getHome());
Assert.assertEquals(dad.getHome().getClass(), Building.class);
}
}