user3799584
user3799584

Reputation: 927

Accessing fields/methods/constructors of an abstract class in its subclass

I was trying to work out how to access/use fields/methods of an abstract class in any subclass and I came across this example on the web.

abstract class Instrument {
     protected String name;

     abstract public void play();
}

abstract class StringedInstrument extends Instrument {
     protected int numberOfStrings;
}

with the concrete example subclass given as

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

I have 5 questions pertaining to this - sorry for asking more than one question but they are highly related.

  1. Is the super() call needed or even valid?. There is no constructor given in the abstract super classes
  2. Can an abstract class even have a constructor given that it can't be instantiated?
  3. Is the keyword "this" necessary in this example concerning this.name?
  4. What is the play() overriding here? When an abstract method is specified in the abstract class doesnt that just tell the compiler the method must be specified by any subclass?
  5. If the Instrument class, StringedInstrument class, and ElectricGuitar class all specified fields called "name" and each had specified constructors (if allowed) how would each name or constructor be accessed in the ElectricGuitar class definition.

Upvotes: 3

Views: 2324

Answers (3)

Andy Thomas
Andy Thomas

Reputation: 86381

Is the super() call needed or even valid?. There is no constructor given in the abstract super classes.

If you leave it out, it implicitly calls super() with no arguments.

An explicit call can be useful if you want to call a superclass constructor with arguments.

Can an abstract class even have a constructor given that it can't be instantiated?

Yes. Because that part of the concrete class still needs to be constructed.

Is the keyword "this" necessary in this example concerning this.name?

No. It can sometimes be useful to eliminate ambiguity to the compiler or human readers.

What is the play() overriding here? When an abstract method is specified in the abstract class doesnt that just tell the compiler the method must be specified by any subclass?

The annotation allows the compiler to verify that the subclass is actually overriding a method in the superclass. It's easy to make a mistake in the method name or signature, and accidentally not override any method.

When you intended to override an abstract method, this helps the compiler point you directly to the mistake.

When you intended to override a concrete method, this provides a compiler error that would otherwise not be present. This can significantly reduce our confusion, surprise and hair loss.

If the Instrument class, StringedInstrument class, and ElectricGuitar class all specified fields called "name" and each had specified constructors (if allowed) how would each name or constructor be accessed in the ElectricGuitar class definition.

Ideally, you'd want to provide a single, private field in the base class Instrument, accessed via an accessor getName() defined in the base class.

That said, you can access the protected superclass fields, by casting. NOTE: Usually this is something to avoid.

 ElectricGuitar guitar = new ElectricGuitar();

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

Upvotes: 3

GokcenG
GokcenG

Reputation: 2801

  1. Even if nothing is done in default constructor of super class, it is better to call super() just in case some other developer define a default constructor and initialize something in it. You don't want to miss that.
  2. Yes it can. But you can't call it directly. Defining a constructor in an abstract class indicates that any sub-class should define a constructor that has parameters at least super has.
  3. As long as you don't have a variable with same name in a lesser scope, you don't need that but it is suggested to use this, for clarity.
  4. Don't think it as overriding. You just provide an implementation for an abstract class. The method in abstract class is just a contract. But you must implement it in your concrete class. Your last sentence is correct. If you don't have any implementation, you can't call this method, so it doesn't cause a problem.
  5. Please make it clear.

Upvotes: 0

rgettman
rgettman

Reputation: 178243

Is the super() call needed or even valid?

It is not needed, but it is valid. All constructor must call a superclass constructor, either explicitly as you have done, or implicitly. If super(); wasn't explicitly included, the compiler would have inserted an implicit call for you.

Can an abstract class even have a constructor given that it can't be instantiated?

Yes, an abstract class can have a constructor. It needs to be called by any subclass constructor.

Is the keyword "this" necessary in this example concerning this.name?

"this" is not necessary here, because there is no local variable or parameter in scope, of the same name, that would hide the instance variable name.

What is the play() overriding here?

It is implementing the abstract play() method. The @Override annotation can be used to indicate that the method overrides or implements a superclass or interface method. Because ElectricGuitar is not abstract, it does need to implement play(), so @Override is not strictly necessary here. However, it is good practice to include this annotation an all methods that are intended to override/implement a method, so that a spelling mistake or typo doesn't mean that the method accidentally doesn't override another method.

If the Instrument class, StringedInstrument class, and ElectricGuitar class all specified fields called "name" and each had specified constructors (if allowed) how would each name or constructor be accessed in the ElectricGuitar class definition?

You cannot directly access fields that are hidden above the superclass. You can access StringedInstrument's name with super.name, but you cannot access Instrument's name with super.super.name, because you can't "chain" super references. To access them directly, name them differently.

You can however provide getter methods, differently named, in each class, that will provide access to each class's name method.

Upvotes: 3

Related Questions