繁体   English   中英

Java抽象类+继承-范围或名称解析

[英]Java abstract class + inheritance — scope or name resolution

我去“刷新”我的Java,只是意识到显然我不了解基本概念! 这是我不知道的简单方法:

public abstract class Robot {

    private String model = "NONAME";

    public Robot() {
        System.out.println("Making a generic " + model + " robot, type: " + this.getClass());
    }

    public String getModel() {
        return model;
    }
}

OK,然后是子类:

public class Terminator extends Robot {
    private String model;

    public Terminator(String model) {
        super();
        System.out.println("Making a " + model + " terminator, type: " + this.getClass());
        this.model = model;
    }
}

然后运行一个简单的示例,期望打印“ T1000”:

    Robot r1 = new Terminator("T1000");
    System.out.println(r1.getModel());

没有骰子! 打印“ NONAME”。 在此之前,我从构造函数获得以下输出:

  • 制作一个通用的NONAME机器人,键入:class com.akarpov.tutorial.Terminator
  • 制作T1000终结器,键入:类com.akarpov.tutorial.Terminator

好了,我看到Java意识到我的类的运行时实例是Terminator,这就是“ new”的意思。 而且,显然,终结者实例的确保留了模型的副本==“ T1000”。 但是在调试器(IntelliJ)中检查r1对象时,我看到两个名为'model'的变量,它们位于不同的地址(显然),具有不同的字符串。 而且,显然,如输出所示,抽象类中的getModel选取了Robot类中定义的默认值,而不是传递给Terminator的构造函数(并保留在对象内部)的默认值。

关于抽象类和继承,我不了解什么?如何使用默认值和默认行为(即getModel)来选择子类中的特定数据(即“ T1000”)? 谢谢! 我很抱歉,如果这已经被很多次困扰了-我看了一下,但是什么都没跳。

您的问题与private修饰符有关……模型变量在两个类中分别存在两次。 私有意味着仅对该类可见。 您可能要使用setter方法。

哦,天哪发布我就知道了。 我的错误是在终结者中声明了另一个String模型,这导致将模型隐藏在Robot中-因此产生了两个副本。 删除它解决了问题。 哎呀!

您遇到的问题是您确实在创建两个变量。 现在,有了代码,调用r1.getModel()您将获得原始的基类model

如果您希望能够从子类中设置模型,则有几种选择。 您可以通过声明一个新的String model朝着开始的方向发展,但是您必须继续从超类重写getModel()方法,以便您的子类将查找自己的model而不是超类model

public class Terminator extends Robot {
    private String model;

    public Terminator(String model) {
        super();
        System.out.println("Making a " + model + " terminator, type: " + this.getClass());
        this.model = model;
    }

    @Override
    public String getModel(){
    return model;
    }
}

另一种选择是在model的超类中创建一个受保护的setter方法的公共类。

public abstract class Robot{

    private String model = "NONAME";

    public Robot() {
        System.out.println("Making a generic " + model + " robot, type: " + this.getClass());
    }

    public String getModel() {
        return model;
    }

    protected void setModel(String str){
        this.model = str;
    }
}

然后,只需将Terminator对象调用setModel(model)然后再调用getModel()然后将获得所需的输出。

让我们看一下这段代码

Robot r1 = new Terminator("T1000");

因此,这将调用Terminator(String)构造函数。 构造函数要做的第一件事是显式调用超类构造函数。 它会自动完成,但是您已经显式地编写了super(),这很好。 超类构造函数执行1件事:

System.out.println("Making a generic " + model + " robot, type: " + this.getClass());

好的,因此它会打印出“制作一个通用的NONAME机器人,键入:Terminator”,因为这是该方法的结果。 它没有任何“模型”变量的本地引用,因此它使用Robot类中定义的实例变量。 然后将控制权交还给Terminator构造函数,后者继续打印输出

System.out.println("Making a " + model + " terminator, type: " + this.getClass());

但是这一次它可以按您期望的那样工作,因为模型变量是由调用该方法的类传递的,因此它遮蔽了您的实例变量。 因此,其值为“ T1000”。 希望这是有道理的

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM