A
Andreas Leitgeb
This is a posting, asking about good programming style.
It's actually two separate questions on a similar setup.
Setup:
Let's say I want to create a class that encapsulates
a Pair of two differently typed things, each of which
may also be null.
class MyFoo {
private X x;
private Y y;
public X getX() { return x; }
public void setX(X vx) { /* verify validity of vx; */ x=vx; }
... ditto for y
}
The class is intended for customization, so neither itself,
nor its attribute-setters and getters shall be final.
Now I want to provide convenience constructors, as the class
is also intended to be conveniently useable "as is":
public MyFoo(X vx, Y vy) {
...
}
Question 1 (mostly about X):
It's said, that from a constructor I shall not call non-final methods,
but I also don't want to either bypass validity checks, nor duplicate
the validation code. Furthermore I'd like subclass constructors to
just pass on their constructors' arguments to the base-class and have
them verified by current class' possibly stronger validation checks
(through overridden setX()).
Oups, seemingly something has gone wrong here with my wishlist.
Is it just my wish for subclasses to be allowed to do "super(vx,vy);"
and have that care about polymorphic validation? Or is this an
acceptable exception to that rule, when documenting it clearly
that any override of setX must never store "this" externally, nor
assume completed construction of current class.
Or maybe the design fault is already some steps lower, than I'm
even aware of?
Question 2:
Multiple overloaded constructors taking either none,X,Y or both
(assuming non-polymorphic validation (i.e. final setX/Y) this
time, to factor out the issues from Q1).
public MyFoo() {}
public MyFoo(X vx) { setX(vx); }
public MyFoo(Y vy) { setY(vy); }
public MyFoo(X vx, Y vy) { setX(vx); setY(vy); }
or is it considered better to do it this way:
public MyFoo(X vx, Y vy) { setX(vx); setY(vy); }
public MyFoo(X vx) { this(vx,null); }
public MyFoo(Y vy) { this(null,vy); }
public MyFoo() { this(null,null); }
Assuming that null is documented to be a legal value, and
is being checked for right after entry into (now final) setX/Y.
I'm aware, that they aren't equivalent. If the differences really
counted in a given case at hand, there'd be no choice in the first
place. Perhaps others have experience with late demands likely
changing things towards forcing one or the other approach.
Finally:
Recommended styles are often about experience others have made. As such
they're not always entirely logically derivable from "I think therefore
I am"
It's actually two separate questions on a similar setup.
Setup:
Let's say I want to create a class that encapsulates
a Pair of two differently typed things, each of which
may also be null.
class MyFoo {
private X x;
private Y y;
public X getX() { return x; }
public void setX(X vx) { /* verify validity of vx; */ x=vx; }
... ditto for y
}
The class is intended for customization, so neither itself,
nor its attribute-setters and getters shall be final.
Now I want to provide convenience constructors, as the class
is also intended to be conveniently useable "as is":
public MyFoo(X vx, Y vy) {
...
}
Question 1 (mostly about X):
It's said, that from a constructor I shall not call non-final methods,
but I also don't want to either bypass validity checks, nor duplicate
the validation code. Furthermore I'd like subclass constructors to
just pass on their constructors' arguments to the base-class and have
them verified by current class' possibly stronger validation checks
(through overridden setX()).
Oups, seemingly something has gone wrong here with my wishlist.
Is it just my wish for subclasses to be allowed to do "super(vx,vy);"
and have that care about polymorphic validation? Or is this an
acceptable exception to that rule, when documenting it clearly
that any override of setX must never store "this" externally, nor
assume completed construction of current class.
Or maybe the design fault is already some steps lower, than I'm
even aware of?
Question 2:
Multiple overloaded constructors taking either none,X,Y or both
(assuming non-polymorphic validation (i.e. final setX/Y) this
time, to factor out the issues from Q1).
public MyFoo() {}
public MyFoo(X vx) { setX(vx); }
public MyFoo(Y vy) { setY(vy); }
public MyFoo(X vx, Y vy) { setX(vx); setY(vy); }
or is it considered better to do it this way:
public MyFoo(X vx, Y vy) { setX(vx); setY(vy); }
public MyFoo(X vx) { this(vx,null); }
public MyFoo(Y vy) { this(null,vy); }
public MyFoo() { this(null,null); }
Assuming that null is documented to be a legal value, and
is being checked for right after entry into (now final) setX/Y.
I'm aware, that they aren't equivalent. If the differences really
counted in a given case at hand, there'd be no choice in the first
place. Perhaps others have experience with late demands likely
changing things towards forcing one or the other approach.
Finally:
Recommended styles are often about experience others have made. As such
they're not always entirely logically derivable from "I think therefore
I am"