[英]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”。 在此之前,我从构造函数获得以下输出:
好了,我看到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.