我有以下Java代码,
class Animal {
private String name="Animal";
public String getName() {
return name;
}
}
class Cat extends Animal {
private String name = "Cat";
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat.getName());
}
}
运行该代码后,我得到了输出Animal
,但我认为它应该是Cat
。在像这样在getName
中覆盖Cat
方法之后,我得到了Cat
。
@Override
public String getName() {
return name;
}
那是因为在子类实例中调用继承的(而不是覆盖的)方法就像cat.getName()
等于调用super.getName()
(因此,我得到Animal
而不是Cat
第一种情况)?还是因为实例变量隐藏的奇怪行为(我不太确定)?
答案 0 :(得分:2)
在子类中重新声明了name
字段,但是在父级中实现了方法getName
时,唯一要读取的字段是父级Animal.name
。
在子类中声明在超类中声明的字段始终是一个坏主意,因为字段不会被“覆盖”,而只是被隐藏。
您打算做的是以下其中一项:
覆盖方法:
class Animal {
private String name="Animal";
public String getName() {
return this.name;
}
}
class Cat extends Animal {
public String getName() {
return "Cat";
}
}
您还可以在子类中声明其他字段,但这仍然不是一个好主意。做到这一点的“正确”方法是重写方法。
或者,将字段暴露给子类,然后更改子类的值:
class Animal {
protected String name = "Animal";
public String getName() {
return name;
}
}
class Cat extends Animal {
public Cat() {
this.name = "Cat";
}
}
这样,就不会混淆哪个字段存储实际值,并且很清楚“覆盖”发生在哪里。
答案 1 :(得分:0)
在Cat类中添加一个具有相同名称的私有作用域变量并不会掩盖Animal类中的变量。要更改行为,您需要重写accessor方法以从Cat类上下文读取变量。
答案 2 :(得分:0)
您可以重载方法,而不是数据成员。 Animal.name
和Cat.name
是两个不同的数据成员。 Animal.getName()
没什么特别的-它返回Animal.name
,并且完全不知道Cat.name
。
一种可能的方法是只拥有一个数据成员Animal.name
,并让每个类以不同的方式初始化它。例如:
class Animal {
private String name;
public Animal() {
this("Animal);
}
protected Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Cat extends Animal {
public Cat() {
this("Cat');
}
}
或者,如果您想依靠类名,可以只使用getSimpleName
:
class Animal {
private String name;
public Animal() {
name = getClass().getSimpleName();
}
public String getName() {
return name;
}
}
class Cat extends Animal {
}
答案 3 :(得分:0)
这是因为cat.getName()
调用getName()
类中的Animal
方法,该方法只知道自己的 name
字段,而不是一个子类。>
可能的解决方案可能是:
class Animal {
private String name = "Animal";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Cat extends Animal {
private String name = "Cat";
public Cat() {
setName(name);
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat.getName());
}
}
我不鼓励您重写方法,因为您应该在以后的每个Animal
子类中使用它。
答案 4 :(得分:0)
您需要重写方法getName()。它是实例级别 您可以在子类中调用它的函数,但不能对其进行修改 而不覆盖功能。所以它正在调用父类函数 具有父类属性。
如果要在输出中显示“ cat”,请覆盖该方法。
答案 5 :(得分:0)
可接受的答案涵盖了一些好的答案,但是我想补充一些内容。
例如
class Animal {
protected String name;
public Animal() {
this.name = "Animal";
}
public String getName() {
return this.name;
}
}
class Cat extends Animal {
public Cat() {
this.name = "Cat";
}
}
例如
class Animal {
private String name = "Animal";
public String getName() {
return this.name;
}
protected void setName(String name) {
this.name = name;
}
}
class Cat extends Animal {
public Cat() {
setName("Cat");
}
}