在其子类中访问抽象类的字段/方法/构造函数

时间:2014-07-16 19:43:12

标签: java inheritance abstract-class

我试图找出如何在任何子类中访问/使用抽象类的字段/方法,我在网上看到了这个例子。

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. 抽象类是否可以使用构造函数,因为它无法实例化?
  4. 是关键字" this"这个例子中有必要关于this.name吗?
  5. 这里有什么游戏()覆盖?如果在抽象类中指定了抽象方法,那只是告诉编译器必须由任何子类指定方法吗?
  6. 如果Instrument类,StringedInstrument类和ElectricGuitar类都指定了所有指定的字段" name"并且每个都指定了构造函数(如果允许)如何在ElectricGuitar类定义中访问每个名称或构造函数。

3 个答案:

答案 0 :(得分:3)

  

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

如果你遗漏它,它会隐式调用没有参数的super()。

如果要调用带参数的超类构造函数,则显式调用可能很有用。

  

抽象类是否可以使用构造函数,因为它无法实例化?

是。因为仍然需要构建具体类的那部分。

  

是关键字" this"关于this.name的这个例子中有必要吗?

没有。有时可以消除编译器或人类读者的歧义。

  

这里有什么游戏()覆盖?如果在抽象类中指定了抽象方法,那么只告诉编译器该方法必须由任何子类指定?

注释允许编译器验证子类实际上是否覆盖了超类中的方法。在方法名称或签名中容易出错,并且意外地覆盖任何方法。

当您打算覆盖抽象方法时,这有助于编译器直接指出错误。

当您打算覆盖具体方法时,这会提供编译器错误,否则该错误将不存在。这可以显着减少我们的困惑,惊讶和脱发。

  

如果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;

答案 1 :(得分:3)

  

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

不需要,但它有效。所有构造函数都必须显式调用超类构造函数,或者隐式调用。如果未明确包含super();,则编译器会为您插入隐式调用。

  

抽象类是否可以使用构造函数,因为它无法实例化?

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

  

是关键字" this"关于this.name的这个例子中有必要吗?

"这"这里没有必要,因为范围中没有本地变量或参数,它们会隐藏实例变量name

  

这里有什么游戏()覆盖?

正在实施abstract play()方法。 @Override注释可用于指示该方法覆盖或实现超类或接口方法。由于ElectricGuitar不是abstract,因此需要实施play(),因此此处@Override并非绝对必要。但是,最好将此注释包含在所有旨在覆盖/实现方法的方法中,以便拼写错误或拼写错误并不意味着该方法不会覆盖其他方法。 / p>

  

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

您无法直接访问隐藏在超类上方的字段。您可以使用StringedInstrument访问name super.name,但无法使用Instrument访问name super.super.name ,因为你不能"链" super引用。要直接访问它们,请以不同方式命名。

但是,您可以在每个班级中提供不同名称的getter方法,以便提供对每个班级name方法的访问权限。

答案 2 :(得分:0)

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