Consider a simple AClass
:
class AClass {
private AContent content;
AClass(AContent content) {
this.content = content;
print();
}
protected void print() {
System.out.println("AClass content is "+ content.getValue());
}
}
Where AContent
is defined by:
class AContent {
int getValue() {
return 1;
}
}
BClass
, extends AClass
, and is initialized by BContent
which extends AContent
as follows :
class BClass extends AClass {
private BContent content;
BClass(BContent content) {
super(content);
this.content = content;
}
@Override
protected void print() {
System.out.println("BClass content is "+ content.getValue());
}
}
Where BContent
is defined by:
class BContent extends AContent{
@Override
int getValue() {
return 2;
}
}
Constructing a BClass
object :
public static void main(String[] args) {
new BClass(new BContent());
}
Yields, as can be expected a NullPointerException
caused by trying to print
System.out.println("BClass content is "+ content.getValue());
before content is initialized.
To overcome it, I thought about two options:
a.Remove print()
invocation from the constructor. This will work but is not desirable for the functionality I need.
b.Make content
static and use a static method to initialize it:
private static BContent content;
BClass(BContent content) {
super(init(content));
}
private static BContent init(BContent content) {
BClass.content = content;
return content;
}
This will work, but looks quiet ugly.
I am seeking advice about how to better construct such code, to make it not only functional but also in line with common practices.
One way is to just pass BContent
to the AClass
constructor. That'll work since BContent
is a subclass of AContent
:
class AClass {
// Make protected so subclasses can access
// (probably better via a protected get method)
protected AContent content;
...
}
class BClass extends AClass {
BClass(BContent content) {
super(content);
}
@Override
protected void print() {
System.out.println("BClass content is "+ content.getValue());
}
}
By the time your print
method gets called content
will have been initialized and you'll be OK.
If you actually need BContent
's type to be known in BClass use generics:
class AClass<ContentT extends AContent> {
// Make protected so subclasses can access
// (probably better via a protected get method)
protected ContentT content;
...
}
class BClass extends AClass<BContent> {
BClass(BContent content) {
super(content);
}
@Override
protected void print() {
// Now if I wanted I could do things with BContent that aren't
// possible with AContent since the type of BContent is known
System.out.println("BClass content is "+ content.getValue());
}
}