我正在尝试创建一个程序来帮助我学习Java继承。但是,在此过程中,我发现了我认为学到的问题。
程序很简单。我有一个名为Gun的超类和一个名为M1911的子类。该程序的目的只是向我表明,您不必重复我也称为shoot()
的方法。但是,这就是问题所在。我想要shoot()
向控制台打印一条消息,说
"GunModel: Pew, pew!"
。在Gun和M1911子类中定义的GunModel和shoot()
具有与从Gun继承的初始值不同的值。这意味着如果M1911的GunModel ==“ M1911”,则方法shoot()
将通过打印来反映出来
"M1911: Pew, pew!"
所有(显然吗?)没有用,因为在我看来,子类内部的值对继承的方法没有影响。那么,为什么是True。另外,我缺少的继承目标是什么?似乎不仅仅是避免重复。
编辑:这是我应该先给出的代码。
public class Gun {
protected String GunModel;
public void shoot() {
System.out.println(GunModel + ": Pew, pew!");
}
}
public class M1911 extends Gun {
public String GunModel = "M1911";
}
这是我为您提供的代码的内容(来自未格式化的注释:
public class Gun
{ protected String GunModel;
public void shoot()
{ System.out.println(GunModel + ": Pew, pew!");
}
}
public class M1911 extends Gun
{
public GunModel = "M1911";
}
正如“用户”在评论中指出的那样,“ GunModel”不能被覆盖,因此这里的内容是两个具有相同名称的不同变量。
这是您可以做的:
public class Gun
{
protected String GunModel = "Gun";
public void shoot()
{ System.out.println(GunModel + ": Pew, pew!");
}
}
public class M1911 extends Gun
{
public M1911()
{
GunModel = "M1911";
}
}
[此后,如果有人执行gunVariable = new M1911()
和gunVariable.shoot()
,它将打印“ M1911:皮尤,皮尤!”。
还有其他方法可以执行此操作-GunModel可以是私有的,可以通过getter和setter方法访问,而不是直接访问。
关于Java代码的字眼:按照惯例,类以大写字母开头,变量以小写字母开头。使用这个普遍遵循的约定,您的变量将被拼写为“ gunModel”而不是“ GunModel”;这样做的好处是很容易分辨出哪些东西是变量,哪些东西是类。通过查看它们后面有括号,可以告诉人们以小写开头的东西是方法。
[继承某些东西时,您可以继承:行为和状态。状态基本上不能被覆盖,在您的代码段中,内存中的M1911实例实际上将具有2个“插槽”-一个GunModel
来自Gun
类,一个GunModel
来自M1911
类。
通常,您在实际程序中不这样做。
另一方面,行为可以被覆盖。我的行为是指方法:
class Gun {
public void shoot() {
System.out.println("Gun : Pew, pew!");
}
}
class M1911 extends Gun {
public void shoot() { // overrides
System.out.println("M1911 : Pew, pew!");
}
}
单个属性(即字段)不能通过继承覆盖。有许多语言可以做到这一点,例如C#和Python。但是,Java仅支持方法的覆盖。有多种处理方法:
public enum Guns
创建一个枚举类final private String gunName
,并在shoot()
方法中引用该字段。此方法必须在枚举上下文中定义,即,不要在枚举的每个列出的实例中重新定义shoot()
,而应动态地调用它:enum Guns {
SOMEGUN("M1911"),
THATGUN("AK-47");
private final String GunModel;
private Guns(String modelName) {
this.GunModel = modelName;
}
public void shoot() {
System.out.println(this.GunModel + ": Pew pew!");
}
}
// Now we can call Guns.SOMEGUN.shoot(), which will return "M1911: Pew pew!" over stdout
等