【问题标题】:Can different subclass values be reflect in inherited methods?不同的子类值可以反映在继承的方法中吗?
【发布时间】:2020-04-20 14:31:23
【问题描述】:

我正在尝试创建一个程序来帮助我学习 Java 的继承。然而,在这个过程中,我发现我以为我学到的东西有问题。

程序很简单。我有一个名为 Gun 的超类和一个名为 M1911 的子类。这个程序的想法只是向我表明你不必重复我做的那种叫做shoot()的方法。然而,问题就在这里。我想让shoot() 向控制台打印一条消息,说

"GunModel: Pew, pew!"

。 GunModel 和shoot() 在 Gun 和 M1911 子类中定义为具有与从 Gun 继承的初始值不同的值。这意味着如果 M1911 有一个 GunModel == "M1911",shoot() 方法将通过打印来反映这一点

"M1911: Pew, pew!"

这一切(显然?)都不起作用,因为在我看来,内部子类的值对继承的方法没有影响。那么,如果是真的,为什么会这样。另外,我缺少的继承目标是什么?这似乎不仅仅是避免重复。

编辑:这是我应该先给出的代码。

public class Gun {  
    protected String GunModel;
    public void shoot() {
        System.out.println(GunModel + ": Pew, pew!");
    }
}

public class M1911 extends Gun {
    public String GunModel = "M1911";
}

【问题讨论】:

  • 感谢您详细解释您要达到的目标。你能包括你试过的代码吗?否则很难知道你哪里出错了。谢谢!
  • 如果你的拍摄方法定义为 getGunModel() + "Pew, pew!" 它应该可以工作。你有一个由 M1911 或其他实现的抽象 getGunModel 方法
  • 嗨,我的第一篇文章很抱歉。即使我很小心,也一定会犯一些错误!
  • Gun.java... public class Gun { protected String GunModel; public void shoot() { System.out.println(GunModel + ": Pew, pew!"); } } M1911.java.... 公共类 M1911 扩展 Gun { public GunModel = "M1911"; } “编辑,抱歉没有格式化,对这一切真的很陌生”。
  • Java 字段不能被覆盖,但方法可以。对 GunModel 字段使用吸气剂。此外,您可能想编辑您的问题,而不是将所有代码放在评论中

标签: java oop inheritance subclass


【解决方案1】:

这是我从您的代码中得到的(来自未格式化的评论):

public class Gun 
{ protected String GunModel; 
  public void shoot() 
  { System.out.println(GunModel + ": Pew, pew!"); 
  } 
} 

public class M1911 extends Gun 
{ 
  public GunModel = "M1911"; 
}

正如 cmets 中的“用户”所指出的,“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: Pew, pew!”。

还有其他方法可以做到这一点——GunModel 可以是私有的,并且可以通过 getter 和 setter 方法而不是直接访问。

关于 Java 代码的一句话:按照惯例,类以大写字母开头,变量以小写字母开头。使用这种普遍遵循的约定,您的变量将被拼写为“gunModel”而不是“GunModel”;这样做的一个优点是很容易分辨哪些是变量,哪些是类。并且可以通过查看它们后面的括号来判断哪些以小写开头的事物是方法。

【讨论】:

  • 这肯定是我要找的!为什么它必须在看起来像构造函数的地方?如果我可以问。还有,谢谢!实际上,我已经为这个问题再次重写了代码,因为我在原始项目中进行了一些更改,试图找出更多的东西。我知道命名约定只是一个错误,并且从刚才学习 C# 开始。 (我应该编辑原始帖子吗?)。
  • 我现在不会编辑原始帖子,这并不重要(此外,它让我的评论令人费解)。它不必在构造函数中,但将它放在那里的一个参数是,从创建 M1911 的实例开始,您希望该变量中的该值。如果有人实例化了它并立即调用了shoot(),那么你已经想要那个值了。我不知道你为什么要把作业放在别的地方。
  • 啊。是的,这确实有道理。干杯,非常感谢您的回答和帮助。我有那种喜欢编程的感觉。学习一些看起来很难但现在相对容易的东西。
  • 还有一个关于 StackOverflow 的问题:任何你认为有用的答案,无论是否针对你的问题,你都可以“投票”它,这给了作者几点回答。对于您自己的问题,您可以选择一个答案来回答您的问题,如果有多个答案,可能是最早的答案,然后单击该答案左侧的复选标记图标 - 这也给出了给作者的一些观点。这就是作者自愿贡献时间而获得奖励的方式。
  • 已排序!我已经投了赞成票。我已经阅读了 StackOverflow 上的一些帖子,只是假设它是自动标记为解决方案的最受好评的评论。再次感谢!
【解决方案2】:

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

  1. 创建一个供应商方法“getGunModel”,它返回 GunModel 而不引用该字段。
  2. 如果武器的身份仅基于其名称,请创建一个枚举类public enum Guns,并在final private String gunName 方法中使用final private String gunName 字段。此方法必须在枚举上下文中定义,即不要在枚举中的每个列出的实例中重新定义shoot(),而是动态调用它:
enum Guns {
    SOMEGUN("M1911"),
    THATGUN("AK-47");

    private final String gunName;

    private Guns(String modelName) {
        this.gunName = modelName;
    }

    public void shoot() {
        System.out.println(this.gunName + ": Pew pew!");
    }
}

// Now we can call Guns.SOMEGUN.shoot(), which will return "M1911: Pew pew!" over stdout

等等

【讨论】:

    【解决方案3】:

    当你继承某些东西时,你可以继承:行为和状态。 状态基本上不能被覆盖,在您的代码 sn-p 中,内存中的 M1911 实例实际上将有 2 个“插槽”——一个来自 Gun 类的 GunModel 和一个来自 M1911 类的 GunModel

    通常你不会在实际程序中这样做。

    另一方面,行为可以被覆盖。行为我的意思是方法:

    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!");
        }
    }
    

    【讨论】:

    • 但是他想用继承来存储一个依赖于他的子类的类型;除了“拍摄”方法之外,它可能还有其他用途。他可以做到这一点,但他不能按照他尝试的方式做到这一点。我提供了一个我认为更接近初衷的答案。
    • 我有点意识到行为可以被覆盖。但是对于像我这样可以扩展到多个子类的小例子,这似乎并没有让我得到任何东西。因为我希望继承能够将父级的变化反映给它的子级。但很高兴知道我可以这样做以获得更多一次性解决方案,干杯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 2011-09-14
    相关资源
    最近更新 更多