Java中的变量继承

Java中的变量继承,java,eclipse,oop,inheritance,Java,Eclipse,Oop,Inheritance,我有一个超类和一堆子类。我希望在每个子类中都有一个具有相同名称的字段,但我不希望在超类中定义它,或者至少我不希望使用该值。这就是我现在拥有的 public abstract class Big { public String tellMe = "BIG"; public Big() {} public void theMethod() { System.out.println ("Big was here: " + tellMe() + ", " +

我有一个超类和一堆子类。我希望在每个子类中都有一个具有相同名称的字段,但我不希望在超类中定义它,或者至少我不希望使用该值。这就是我现在拥有的

public abstract class Big {

    public String tellMe = "BIG";

    public Big() {}

    public void theMethod() {
        System.out.println ("Big was here: " + tellMe() + ", " + tellMe);
    }
    public String tellMe() {
        return tellMe;
    }
}

public class Little extends Big{

    public String tellMe = "little";
    public Little(){}

    public String tellMe() {
        return "told you";
    }
    public static void main(String [] args) {
        Little l = new Little();
        l.theMethod();
    }
}
当我运行很少时,这就是输出

大人物在这里:告诉过你,大人物

我不知道为什么“告诉过你”会被打印出来,而tellMe指的是“大”。怎么可能两者都是真的

我的问题是我希望方法tellMe()是大的,并且在所有子类中定义变量tellMe(它将实际返回)。我唯一能做到这一点的方法是,正如我所写的,在每个子类中重写tellMe()方法。但这难道不是违背了继承的全部目的吗???请帮忙


编辑:我在子类中不使用构造函数。我想要的是一个可以在所有子类中设置的字段,以及一个在super中使用这些值的方法。我不明白为什么这是不可能的,因为每个子类都必须实现它,所以它是有意义的。。。如果这根本不可能,请告诉我您可以覆盖
Big的值。告诉我
Little
的构造函数中的

摆脱:

public String tellMe = "little";
并将
Little
构造函数更改为:

public Little(){
    tellMe = "little";
}

在这一点上,您还可以摆脱
Little.tellMe()

字段与方法不同,不是虚拟的。因此,声明与层次结构中另一个类中的字段同名的字段是一个坏主意。方法
中引用的字段总是来自
Big
(即,当您使用相同的名称声明一个字段时,它在替换类的范围内仅隐藏旧字段,而不替换它)

一种解决方案是重写从当前类获取字段的方法:


method
中,将
tellMe
字段替换为
getTellMe()
,对于所有类,重写
getTellMe()
以返回正确的值(或隐藏超类字段的字段)。

而不是在Big中定义tellMe(因为您说过不想在Big中定义/使用该值)您可以在大屏幕中创建函数:

public abstract String tellMeString();

并在每个子类中这样定义(很少):

然后该方法可以执行:

System.out.println ("Big was here: " + tellMe() + ", " + tellMeString());

在这种情况下,您根本不必定义变量“tellMe”,只需在每个子类中重写tellMeString以返回不同的字符串。

字段不会像预期的那样继承。您可以从子类访问超级类的字段(除非它是私有的)。但不能“覆盖”字段。这就是为什么超级类
Big
中实现的方法使用的
tellMe
使用在同一类中定义的变量

如果您想要继承,请使用方法。例如,您可以实现方法“tellMe()”,该方法在超类中返回
“BIG”
,在子类中返回
“little”

class Big {
    protected String tellMe() {
        return "BIG";
    }
}
class Little {
    @Override
    protected String tellMe() {
        return "Little";
    }
}
或者,您可以在构造函数中初始化变量
tellMe

class Big {
    private String tellMe;
    public Big() {
        this("BIG");
    }
    protected Big(String tellMe) {
        this.tellMe = tellMe;
    }
    protected String tellMe() {
        return "BIG";
    }
}
class Little {
    public Little() {
         super("Little");
    }
}

现在
new Little().tellMe()
将返回“Little”:超类中的变量是在构造对象时初始化的;在super类中定义的方法返回了此变量

您要做的是隐藏super class字段,而不是像。 而且也有人说这样做不是个好主意

因此,动态查找不会像方法那样工作。如果从子类中读取变量,它将采用“its”字段值。 在头等舱,另一个

在Java中可以重写的是行为,因此我建议 定义一个方法

public String tellMe() {
  return "Whatever";
}

可以在子类中重写以返回所需的任何字符串。

方法可以被重写,字段在调用它们的范围内可见

static class Big {
    String field = "BIG";
    String bark()   { return "(big bark)"; }

    void doIt() {
        System.out.format("field(%s) bark(%s)\n", field,bark());
    }
    void doIt2()    {
        System.out.format("2:field(%s) bark(%s)\n", field,bark());
    }
}

static class Small extends Big {
    String field = "small";
    String bark()   { return "(small bark)"; }
    void doIt2()    {
        System.out.format("2:field(%s) bark(%s)\n", field,bark());
    }
}

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

    Big b = new Big();
    b.doIt();
    b.doIt2();

    Small s = new Small();
    s.doIt();
    s.doIt2();
}
输出为:

field(BIG) bark((big bark))
2:field(BIG) bark((big bark))
field(BIG) bark((small bark))
2:field(small) bark((small bark))
由于doIt()是在大类中定义的,因此它将始终看到字段的大版本。doIt2()在Big中定义,但在Small中被重写。Big.doIt2()可以看到字段的大版本,Small.doIt2()可以看到字段的小版本


正如其他人所指出的,这样做是一个非常糟糕的主意-更好的方法是在子类构造函数中设置新值,或者使用一个被重写的方法。

方法
tellMe()
和字段
tellMe
绝对没有关联,不管名称如何。我知道。。。我不知道;我无法理解此评论的目的,但谢谢你。我喜欢公共字段是最终的,但是如果你相信程序员,这是一个好的解决方案。不,这不是一个好的解决方案。当继承的全部目的是压缩代码时,为什么我必须将确切的smae行放在数百个子类中?我甚至不使用构造函数,所以这对我没有帮助?与声明和隐藏字段的解决方案相比,此解决方案所需的代码更少。@ColeCanning:您只需向每个子类添加一行代码。我看不出你会做得更好。我根本不在我的子类中使用构造函数。我也知道我提供的代码是浪费和荒谬的,这就是为什么我在这里。我必须提供最接近我需要的方式这是我的问题。当继承的目的是压缩代码时,为什么有必要在我的子类中创建数百次相同的精确方法呢。。。为什么没有这样一个抽象字段,我可以在大范围内拥有它,并在我所有的小范围内定义它呢?
getTellMe(){return“Text”}
tellMe=“Text”长不了多少。这只是JVM的设计:字段不是虚拟的。声明和隐藏一组字段肯定更糟糕:为每个字段的每个实例分配内存。参见Keith Randall的解决方案-他更改字段而不是声明新字段。我在子类中不使用构造函数。我也希望能够直接编辑此字段。。。所以我会做出一个决定
field(BIG) bark((big bark))
2:field(BIG) bark((big bark))
field(BIG) bark((small bark))
2:field(small) bark((small bark))