Reputation: 927
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.
Upvotes: 3
Views: 2324
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
Reputation: 2801
super()
just in case some other developer define a default constructor and initialize something in it. You don't want to miss that.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.Upvotes: 0
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