【问题标题】:Accessing fields/methods/constructors of an abstract class in its subclass在其子类中访问抽象类的字段/方法/构造函数
【发布时间】:2014-07-16 19:43:12
【问题描述】:

我试图弄清楚如何在任何子类中访问/使用抽象类的字段/方法,我在网络上遇到了这个示例。

abstract class Instrument {
     protected String name;

     abstract public void play();
}

abstract class StringedInstrument extends Instrument {
     protected int numberOfStrings;
}

具体示例子类为

public class ElectricGuitar extends StringedInstrument {

     public ElectricGuitar() {
          super();
          this.name = "Guitar";
          this.numberOfStrings = 6;
     }

     public ElectricGuitar(int numberOfStrings) {
          super();
          this.name = "Guitar";
          this.numberOfStrings = numberOfStrings;
     }

     @Override
     public void play() {
          System.out.println("An electric " + numberOfStrings + "-string " + name
                + " is rocking!");
     }
}

我有 5 个与此相关的问题 - 很抱歉问了多个问题,但它们高度相关。

  1. 是否需要调用 super() 或者是否有效?抽象超类中没有给出构造函数
  2. 如果抽象类不能被实例化,它甚至可以有一个构造函数吗?
  3. 对于this.name,本例中是否需要关键字“this”?
  4. play() 在这里覆盖了什么?在抽象类中指定抽象方法时,不只是告诉编译器该方法必须由任何子类指定吗?
  5. 如果 Instrument 类、StringedInstrument 类和 ElectricGuitar 类都指定了名为“name”的字段,并且每个字段都有指定的构造函数(如果允许),那么如何在 ElectricGuitar 类定义中访问每个名称或构造函数。

【问题讨论】:

    标签: java inheritance abstract-class


    【解决方案1】:

    是否需要调用 super(),甚至是否有效?

    它不是必需的,但它是有效的。所有构造函数都必须调用超类构造函数,或者像您所做的那样显式地调用,或者隐式地调用。如果super(); 没有被显式包含,编译器会为你插入一个隐式调用。

    如果抽象类不能被实例化,它甚至可以有一个构造函数吗?

    是的,抽象类可以有构造函数。它需要被任何子类构造函数调用。

    这个例子中关于this.name的关键字“this”是否必要?

    这里不需要“this”,因为范围内没有同名的局部变量或参数会隐藏实例变量name

    play() 在这里覆盖了什么?

    它正在实现abstract play() 方法。 @Override 注解可用于指示该方法覆盖或实现了超类或接口方法。因为ElectricGuitar不是abstract,它确实需要实现play(),所以@Override在这里不是绝对必要的。但是,最好将此注释包含在旨在覆盖/实现方法的所有方法中,这样拼写错误或拼写错误并不意味着该方法意外地没有覆盖另一个方法。

    如果 Instrument 类、StringedInstrument 类和 ElectricGuitar 类都指定了名为“name”的字段,并且每个字段都有指定的构造函数(如果允许),那么如何在 ElectricGuitar 类定义中访问每个名称或构造函数?

    您不能直接访问隐藏在超类之上的字段。您可以使用super.name 访问StringedInstrumentname,但您不能使用super.super.name 访问Instrumentname,因为您不能“链接”super 引用。要直接访问它们,请以不同的方式命名它们。

    但是,您可以在每个类中提供名称不同的 getter 方法,这些方法将提供对每个类的 name 方法的访问。

    【讨论】:

    • 这句话似乎不正确:“您不能直接访问隐藏在超类之上的字段。”您可以访问这些字段,而不是通过链接 super,而是通过强制转换。例如,请参阅我的答案。
    • @rgettman - 感谢您的澄清。如果抽象类有自己的构造函数,子类可以重载它(使用不同的参数列表)还是覆盖它(使用相同的参数列表)
    • 构造函数不是继承的,所以你不能覆盖它们。但是,您可以在子类中定义您想要的任何构造函数,只要它以某种方式调用超类构造函数,无论是隐式地还是显式地作为构造器主体中的第一条语句。您可以通过在一个类中拥有多个构造函数来重载构造函数。
    【解决方案2】:

    是否需要调用 super() 甚至有效?抽象超类中没有给出构造函数。

    如果你忽略它,它会隐式调用不带参数的 super()。

    如果您想使用参数调用超类构造函数,显式调用会很有用。

    如果抽象类不能被实例化,它甚至可以有一个构造函数吗?

    是的。因为具体类的那部分还需要构造。

    这个例子中关于this.name的关键字“this”是否必要?

    没有。消除对编译器或人类读者的歧义有时会很有用。

    这里的 play() 覆盖了什么?在抽象类中指定抽象方法时,不就是告诉编译器该方法必须由任何子类指定吗?

    注解允许编译器验证子类实际上覆盖了超类中的方法。在方法名称或签名中很容易出错,并且不小心覆盖任何方法。

    当您打算重写 abstract 方法时,这有助于编译器直接指出错误。

    当您打算重写 具体 方法时,这会提供一个编译器错误,否则该错误不会出现。这可以显着减少我们的困惑、惊讶和脱发。

    如果 Instrument 类、StringedInstrument 类和 ElectricGuitar 类都指定了名为“name”的字段,并且每个都有指定的构造函数(如果允许),那么如何在 ElectricGuitar 类定义中访问每个名称或构造函数。

    理想情况下,您希望在基类 Instrument 中提供一个私有字段,通过基类中定义的访问器 getName() 进行访问。

    也就是说,您可以通过强制转换访问受保护的超类字段。 注意: 通常这是要避免的。

     ElectricGuitar guitar = new ElectricGuitar();
    
     String guitarName = guitar.name;
     String stringInstrumentName = ((StringedInstrument) guitar).name;
     String instrumentName = ((Instrument) guitar).name;
    

    【讨论】:

      【解决方案3】:
      1. 即使在超类的默认构造函数中没有做任何事情,最好还是调用super(),以防其他开发人员定义默认构造函数并在其中初始化某些内容。你不想错过。
      2. 是的,它可以。但是你不能直接调用它。在抽象类中定义构造函数表示任何子类都应该定义具有至少 super 参数的构造函数。
      3. 只要在较小的范围内没有同名的变量,就不需要它,但为了清楚起见,建议使用它。
      4. 不要认为它是overriding。您只需为抽象类提供一个实现。抽象类中的方法只是一个契约。但是你必须在你的具体类中实现它。你最后一句话是对的。如果你没有任何实现,你不能调用这个方法,所以它不会造成问题。
      5. 请说清楚。

      【讨论】:

      • 不确定如何使其更清晰。如果您添加了“字符串名称;”在 StringedInstrument 和 ElectricGuitar 的定义中。但是 nvm - 问题已经得到解答。
      • 在上面的#1 中,如果你不显式调用 super(),它会被隐式调用。无论您是否调用 super(),都会调用超类默认构造函数。在上面的#2 中,不需要子类来定义具有与超类相同签名的构造函数。一个子类可以提供更少的构造函数,具有完全不同的签名。
      猜你喜欢
      • 1970-01-01
      • 2021-05-09
      • 1970-01-01
      • 2020-06-18
      • 2016-08-20
      • 1970-01-01
      • 2010-09-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多