可以在继承的方法中反映不同的子类值吗?

问题描述 投票:1回答:3

我正在尝试创建一个程序来帮助我学习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";
}
java oop inheritance subclass
3个回答
1
投票

这是我为您提供的代码的内容(来自未格式化的注释:

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”;这样做的好处是很容易分辨出哪些东西是变量,哪些东西是类。通过查看它们后面有括号,可以告诉人们以小写开头的东西是方法。


0
投票

[继承某些东西时,您可以继承:行为和状态。状态基本上不能被覆盖,在您的代码段中,内存中的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!");
    }
}

0
投票

单个属性(即字段)不能通过继承覆盖。有许多语言可以做到这一点,例如C#和Python。但是,Java仅支持方法的覆盖。有多种处理方法:

  1. 创建一个提供程序方法“ getGunModel”,该方法返回GunModel而不引用该字段。
  2. 如果武器的身份仅基于其名称,则使用字段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

© www.soinside.com 2019 - 2024. All rights reserved.