Java抽象类字段重写

Java抽象类字段重写,java,class,overriding,field,abstract,Java,Class,Overriding,Field,Abstract,我有一个抽象类,它应该实现一个公共字段,这个字段是一个接口或另一个抽象类 大概是这样的: public abstract class GenericContainer { public GenericChild child; } public abstract class GenericChild { public int prop1=1; } public abstract class SpecialChild extends GenericChild { publ

我有一个抽象类,它应该实现一个公共字段,这个字段是一个接口或另一个抽象类

大概是这样的:

public abstract class GenericContainer {
    public GenericChild child;
}

public abstract class GenericChild {
    public int prop1=1;
}

public abstract class SpecialChild extends GenericChild {
    public int prop1=2;
}
public class ExternalClass {
    public GenericContainer container=new SpecialContainer();
    public int test() {
         return container.child.prop1
    }
}
现在我有了另一个专门的类容器:

public abstract class SpecialContainer extends GenericContainer {
    public SpecialChild child=new SpecialChild(); //PAY ATTENTION HERE!
}
Java允许我编译这个,我想象
SpecialContainer
中的字段
child
会自动重载
GenericContainer的字段
child
。。。 问题是: 我说的对吗?孩子会自动“超载”吗

还有一个更重要的问题,如果我有另外一节课,像这样:

public abstract class GenericContainer {
    public GenericChild child;
}

public abstract class GenericChild {
    public int prop1=1;
}

public abstract class SpecialChild extends GenericChild {
    public int prop1=2;
}
public class ExternalClass {
    public GenericContainer container=new SpecialContainer();
    public int test() {
         return container.child.prop1
    }
}
test()
将返回1或2?我指的是
GenericContainer
container字段
prop1
将调用什么,通用还是特殊? 如果特殊的prop1被声明为String(是的,java允许我在这种情况下也编译),会怎么样

谢谢

关于

…我想象SpecialContainer中的字段“child”会自动重载GenericContainer的字段“child”

不会。字段不会被重写,只有方法会被重写

这就是为什么优先使用(可重写的)getter和setter方法而不是直接访问字段的原因之一。您的字段几乎都应该是私有的

至于您的设计,您的SpecialContainer类不需要有SpecialChild字段,而是应该将SpecialChild对象放置在GenericChild字段中

Java允许我编译这个,我认为 SpecialContainer正在自动重载 通用容器


首先,继承性不适用于变量。字段(Insatnce变量)不会在子类中被重写。只有在子类中用
public、protected或default

标记时,字段才可见。在Java中,数据成员/属性不是多态的。重载意味着字段将具有不同的值,具体取决于访问它的类。子类中的字段将隐藏超类中的字段,但两者都存在根据引用类型调用字段,而方法用于实际对象。你可以自己试试


它被称为变量隐藏/阴影,有关更多详细信息,请查看

它没有覆盖任何内容,您只是在当前类范围中隐藏原始字段。如果将变量与子类型一起使用,则仍可访问原始属性。例如:

abstract class GenericContainer {
    public GenericChild child;       
}

abstract class GenericChild {
    public int prop1=1 ;
}

class SpecialChild extends GenericChild {
    public int prop1=2;
}

class SpecialContainer extends GenericContainer {
    public SpecialChild child;
}

public class Main {

    public static void main( String ... args ) {

        GenericContainer container = new SpecialContainer();
        container.child = new SpecialChild();

        System.out.println( container.child.prop1 );

        SpecialChild child = (SpecialChild) container.child;        
        System.out.println( child.prop1 );
    }

}
这将打印1,然后打印2

SpecialChild
您还可以使用
super
升级一级:

class SpecialChild extends GenericChild {
    public int prop1=2;

    public int getOriginalProp1() {
        return super.prop1;
    }

}

为了回答您的问题,它维护两个实例。根据引用容器的方式(通过抽象或impl)确定引用的变量

public class Test {

   public abstract class Container{
       public Generic gen = new Generic();
   }

   public class ContainerImpl extends Container{
       public GenericImpl gen = new GenericImpl();
   }

   public class Generic{
       public int prop = 0;
   }

   public class GenericImpl extends Generic{
       public int prop = 1;
   }

   public Test(){
       Container c = new ContainerImpl();
       System.out.println(c.gen.prop); // Outputs "0"
       System.out.println(((ContainerImpl)c).gen.prop); // Output "1"
   }

   public static void main(String[] args) {
      new Test();
   }

}
眼前更大的问题是,你为什么要设计这样的东西?我想你是从理论的角度问的


我的2美分,这不是很好的OO设计。最好将公共变量设为私有变量,并通过构造函数或属性设置器分配它们的值。实际上,它会在代码中导致意外的结果。

为什么没有人注意到该程序将抛出
NullPointerException

具有相同名称的子类的
字段
将隐藏超类的
字段
。没有使用
字段覆盖
。只有使用方法才能重写

作者的原始代码:

public abstract class GenericContainer {
    public GenericChild child;
}

public abstract class GenericChild {
    public int prop1=1;
}

public abstract class SpecialChild extend GenericChild {
    public int prop1=2;
}

public abstract class SpecialContainer extends GenericContainer {
    public SpecialChild child=new SpecialChild(); //PAY ATTENTION HERE!
}

public class ExternalClass {
    public GenericContainer container=new SpecialContainer();
    public int test() {
         return container.child.prop1
    }
}

不。字段不会被重写,只有方法会被重写。因此,如果在“SpecialChild”中我有一个使用prop1的方法,它在第一次调用时会得到什么?1还是2?我尝试过,从SpecialChild中删除prop1将允许我在SpecialChild中编写一个也使用prop1的方法,如果它仅在GenericChild中定义。。。所以我认为会发生一种过载……您可以尝试运行它。上面的程序抛出“NullPointerException”。对于您提出的问题,其答案是字段不能被覆盖。如果在子类中定义了相同的字段名,则子类字段将隐藏超类的字段。@AmitG yes,因为在GenericContainer中我没有初始化泛型子类。在我的整个项目中,它起了作用。