首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可以继承方法访问Java中的子类字段

可以继承方法访问Java中的子类字段
EN

Stack Overflow用户
提问于 2015-06-17 03:48:26
回答 4查看 2K关注 0票数 1

我很难理解遗产。在下面的代码中,为什么继承的方法不能访问子类中的字段?是否有任何方法可以访问子类字段而不覆盖继承的方法?

代码语言:javascript
复制
class Fish {
    private String fishType = "Fish";
    public String getFishType() {
        return fishType;
    }
}

class Marlin extends Fish {
    private String fishType = "Marlin";
}

public class InheritanceTest {
    public static void main(String[] args) {
        Fish fish1 = new Fish();
        Fish marlin1 = new Marlin();
        System.out.println(fish1.getFishType());
        System.out.println(marlin1.getFishType());
    }
}

这段代码打印

代码语言:javascript
复制
Fish
Fish

但我还以为

代码语言:javascript
复制
Fish
Marlin

每个人似乎都是基于私密的字符串来回答的,但是即使我把字段改为公开的,我仍然有问题。问题不在于继承私有字段。

请参阅下面更新的代码。

代码语言:javascript
复制
class Fish {
    public String fishType = "Fish";
    public String getFishType() {
        return fishType;
    }
}

class Marlin extends Fish {
    public String fishType = "Marlin";
}

public class InheritanceTest {
    public static void main(String[] args) {
        Fish fish1 = new Fish();
        Marlin marlin1 = new Marlin();
        System.out.println(fish1.getFishType());
        System.out.println(marlin1.getFishType());
    }
}

输出结果和我的预期是相同的。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-10-25 16:38:38

虽然@Makoto给出了一个公平的答案,但我觉得OP问题的意图并没有得到正确的回答。

问题是为什么马林类中重新声明的fishType在对Marlin实例调用时不被继承的getFishType()方法所尊重。

当您考虑到方法查找的工作方式(与字段查找不同)时,这就更加奇怪了:如果您添加了一个方法Fish::getT()protected String getT() {return "Fish";}并在Marlin::getT()中用protected String getT() {return "Marlin";}覆盖它,并且在Fish::getFishType()中调用这个新方法而不是访问字段,那么对marlin1.getFishType()的调用实际上会产生"Marlin“。-在这里,子类方法使用在继承的方法中,而不是同名的父方法。这是因为方法查找总是从当前实例开始。

我认为答案来自@Makoto给出的Java文档的引用:重新声明的字段“隐藏”继承层次结构中所有其他可访问的同名声明(而重声明的方法“覆盖”相同名称和签名的先前声明)。我认为这意味着Marlin.fishType必须被认为是一个与Fish.fishType完全不同的符号(无意中同名)。Fish.getFishType()只是看到了它自己的版本。

票数 1
EN

Stack Overflow用户

发布于 2015-06-17 03:50:03

首先,属于private的字段(和方法)是而不是继承的。您的Marlin类甚至不知道它的父字段。

其次,Java将根据您在运行时使用的实例选择最合适的方法进行调用。因为Marlin没有定义getFishType方法,所以它将使用它的父方法。

可以采取以下几种方法:其中之一是在getFishType中重写Marlin方法

代码语言:javascript
复制
@Override
public String getFishType() {
    return fishType;
}

使用新代码,您实际上是隐藏变量,在Marlin中重新声明它。

如果类声明了一个具有特定名称的字段,那么该字段的声明就会在超类和类的超级接口中隐藏具有相同名称的字段的任何和所有可访问声明。

这很容易通过不重新声明变量来解决;相反,在构造时分配您想要的值。

代码语言:javascript
复制
public Marlin() {
    fishType = "Marlin";
}

或者,为了保持代码的简洁性,您可以通过使用父方法来重构类,而不是在子方法中重写它。这确实需要父类中的两个构造函数。

代码语言:javascript
复制
class Fish {
    private final String fishType;

    // Default constructor; used in nominal cases
    public Fish() {
        this("Fish");
    }

    // Constructor used to populate the fishType field
    public Fish(final String fishType) {
        this.fishType = fishType;
    }

    public String getFishType() {
        return fishType;
    }
}

class Marlin extends Fish {
    public Marlin() {
        super("Marlin"); // invoke super's constructor
    }
}

同样,由于在getFishType中没有合适的方法Marlin,所以它将查找Fish类并使用它的方法。然而,这一次,我们真正想要实现的价值正是我们所期望的。

票数 5
EN

Stack Overflow用户

发布于 2015-06-17 03:52:41

您必须在Marlin类中重写getFishType()。私有属性仅在类中可见。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30882007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档