我是Java的新手。我有以下课程:
public abstract class Beverage {
String description = "Unknown beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
和
public class DarkRoast extends Beverage {
String description = "Dark roast";
@Override
public double cost() {
return 0.99;
}
}
当我构造一个新的DarkRoast
对象时:
Beverage beverage2 = new DarkRoast();
我希望它的desctiption等于“Dark roast”:
assertEquals("Dark roast", beverage2.getDescription());
但实际上它是“未知的饮料”。我知道我应该实现设置描述的DarkRoast构造函数,但我不知道为什么,我不知道它是如何在内部工作的。子类字段不应该覆盖超类字段吗?
答案 0 :(得分:4)
子类字段是否应该覆盖超类字段?
否 - 子类字段实际上是一个全新的字段。由于您要分配给超类字段,您需要创建一个这样的构造函数:
public DarkRoast()
{
description = "Dark roast";
}
(这与方法cost()
不同 - 从技术上讲,当你覆盖非抽象方法时,你仍然“有点”拥有旧方法。
答案 1 :(得分:0)
因为被调用的getDescription
方法是类Beverage
的方法(DarkRoast
没有自己的方法),所以方法getDescription
访问了他的description
1}} property,其值为"Unknown beverage"
。
答案 2 :(得分:0)
您不会覆盖子类中的.getDescription()
方法;因此,调用的方法是Beverage
中的方法,而Beverage
中的方法只知道description
中Beverage
已声明(并在此情况下已初始化)return this.description;
本身。
您可以使用它来显示所有子类中的值:
public abstract class Beverage
{
private final String description;
public abstract Beverage(final String description)
{
this.description = description;
}
public final String getDescription()
{
return description;
}
// etc
}
// Subclass
public class DarkRoast
extends Beverage
{
public DarkRoast()
{
super("Dark Roast");
}
}
然而,有一个更好的方法来解决这个问题;那就是:
Beverage
你应该注意到,开始描述一个“未知的饮料”是没有意义的。 Beverage
是抽象的,无法实例化!这里提出的解决方案基本上禁止任何人在没有描述的情况下创建{{1}},因此最终会实现双赢。
答案 3 :(得分:0)
如果子类必须始终提供描述,那么可以使getDescription为abstract,这会强制子类实现并返回一个值。只是另一种技术。
答案 4 :(得分:0)
允许类隐藏成员。当您在类中声明一个成员并在子类中声明一些具有相同名称的成员时,您将隐藏它但不会覆盖它。
如果要为实现抽象类的每个类提供唯一名称,则应声明一个抽象方法
public abstract String getDescription();
或者您可以将值传递给成员。
BaseClass(String description) {
this.description = description;
}
然后在子类中,您可以使用super
来访问构造函数
ChildClass(String description) {
super(description);
}
关键字super
允许您直接访问父类的成员。
所以,如果你上课,你可以做这样的事情
private void test() {
System.out.println(super.description); //This will refer to parent class
System.out.println(this.description); //This will refer to child class
}
因此,当您声明一个字段时,您始终会创建一个新的参考点。
答案 5 :(得分:0)
问题是有2个名为description的属性,一个在超类'Beverage'中,一个在子类'DarkRoast'中,并且由于您使用Beverage作为引用类型,您将获得描述属性/实例变量引用类和子类的引用类是阴影的(至少根据我在Java中的愚蠢知识无法访问)。
您不需要在子类中再次定义属性,因为它已经存在,所以基本上如果从DarkRoast类中删除属性描述,您会发现它也会打印未知的描述,因为它已经存在
为了使事情更加清楚,请尝试使用此代码来查看有两个不同的描述实例变量。
public class DarkRoast extends Beverage {
String description = "Dark roast";
public String getDescription() {
return description;
}
public String getSuperDescription() {
return super.description;
}
@Override
public double cost() {
return 0.99;
}
public static void main(String[] args) {
DarkRoast b = new DarkRoast();
System.out.println(b.getDescription());
System.out.println(b.getSuperDescription());
}
}
要查看阴影,请尝试执行以下操作:
public static void main(String[] args) {
Beverage b = new DarkRoast();
DarkRoast b2 = new DarkRoast();
System.out.println(b.description);
System.out.println(b2.description);
}