comparison of protected members vs abstract classes

S

Sideswipe

I often debate to myself the best approach to an inheritance
implementation problem.

Say I have a abstract base class that does all the heavy lifting for a
task. The only thing subclasses need do is fill in some blanks -- data
blanks not functional.

3 ways I know of doing it are:

1) create a constructor in the parent and pass it up the stack

public MySubclass(Int x,String y) {
super(x,y);
}

pro -- less subclass code. super.x and super.y are unmodifiable by the
subclass
con -- creates a rigid constructor dependency between parent and
child. Multiple constructors become difficult to maintain

2) use protected member objects set during construction.

public MySubClass(int x,String y) {
super.x = x;
super.y = y;
}

pro: no dependency on parent constructor. Child constructor also gains
added flexibility
con: super.x and super.y are always modifiable to the child class.
This can create bad situations with misbehaving children.

3) Use abstract method to force child classes to give info.

public abstract class SomeClass {
public abstract int getX();
public abstract String getY();
}

public class MySubClass extends SomeClass {

public int getX() {return this.x;}
public String getY() {return this.y;}
}

pro: no constructor dependencies, no access to raw member variable in
parent, child may also change values anytime between calls to said
abstract methods (data on as-needed basis)

con: can create very repetitive code across several child classes.
Especially when simple return values are needed.

Experience has taught me to stay away from 1. 2 doesn't generally
represent a problem if you are writing the super and subclasses, but
because it leaves the door open for abuse later I generally lean
toward the 3rd.

I was looking for more discussion on this subject. Any thoughts?

Christian Bongiorno
http://christian.bongirono.org
 
R

Roedy Green

I was looking for more discussion on this subject. Any thoughts?

In the example you gave I don't see enough difference to fret over it.
Perhaps with messier examples the difference would become obvious.

With constructors, the specification is positional, terse, but
confusing with a large number of parms.

In both schemes you ensure all data is provided.

I tend to like the abstract method approach. It gives flexibility to
the implementor to use either constructors, constants or complex
calculations.
 
E

Ed Kirwan

Sideswipe said:
I often debate to myself the best approach to an inheritance
implementation problem.

Say I have a abstract base class that does all the heavy lifting for a
task. The only thing subclasses need do is fill in some blanks -- data
blanks not functional.
Snip.
Christian Bongiorno
http://christian.bongirono.org

I know one author - H.S. Lahman - who would strongly, strongly suggest that
if you have subclasses that only fill in the data-blanks in the base class
then you should not have subclasses at all. Instead, you should only have
the base class and supply the required data in its constructor.

He claims that behaviour resides in the class invariant: which in this case
is everything-but-the-data, and so having subclasses pretending that
they're doing anything useful is just clutter.

I find his writing dense but rewarding; if you're willing to give it a go:

http://pathfinderpeople.blogs.com/hslahman/invariants_and_parametric_polymorphism/index.html
 
S

Sideswipe

Well, I fully admit it does give more clutter, but it also makes it
much more clear and, OO is about Data encapsulation -- which is what
subclasses filling in the blanks definitely is.

Why is it clearer? Because when I am debugging I don't have to figure
out which, of 100 different instantiations, was used to create an
instance of the object that is behaving wrong and knowing which
parameters were passed at runtime. The "parameters" are declared
static inside the subclass. Because it's a method, I also have the
ability in the subclass to intercept anytime that data is used. I
tend to agree with the prior poster about the extra flexibility being
worth the cluster. The potential is that these classes COULD be
useful. Anyone with some time in the field will tell you that
flexibility counts for a lot.

This author says.... but, what do you think? Do you agree? Djikstra
claimed, until his death, that OO was unnecessary and that CS student
should be taught to formally prove their code -- there by nullifying
the need for a highly organized language like Java. Of course, his
fanaticism ignored that fact that provability of code requires a
closed system where non-determinism can't be introduced through
Network, disk io and multi-threading and, of course, silly users. To
say nothing of the time and cost to formally prove anything.


Christian Bongiorno
http://christian.bongiorno.org
 
E

Ed Kirwan

Sideswipe said:
Well, I fully admit it does give more clutter, but it also makes it
much more clear and, OO is about Data encapsulation -- which is what
subclasses filling in the blanks definitely is.

I tend to agree that having the extra classes is clearer than not having
them. This clarity, however, does have its price (the extra classes
themselves) so I suppose it depends on the problem being solved (what
doesn't?).

And as a slight aside, OO for me is more about encapsulating variation (be
that behavioural or data) than pure data encapsulation. Of course, to each
his own.
snip

This author says.... but, what do you think? Do you agree?

Well, as you ask, I've been trying to think of encounters I've had that are
relevant to your question, and I think I've spotted one - but in this case,
the classes are very simple, perhaps so much so that they bare no true
relation to your own classes: you must be the judge. Again, I find myself
thinking that the nature of the problem itself decides.

Anyway, I've a little poker game that offers three different levels of
computer opponent, called a Type 1 AI, a Type 2 AI and a Type 5 AI. The
game's configurable via a BinaryOption class, and I've three subclasses
called Type1AIOption, Type2AIOption and Type5AIOption that say whether a
particular AI is allowed to play in a particular game:

http://www.edmundkirwan.com/servlet/fractal/cs1/code/package123.html

http://www.edmundkirwan.com/servlet/fractal/cs1/code/package124.html

http://www.edmundkirwan.com/servlet/fractal/cs1/code/package125.html

All these subclasses just assign variables in the base BinaryOption class
and contain no behaviour of their own.

I think, however, that Mister Lahman's advice has rubbed off onto me,
because in my current project I also use BinaryOption, and I presently have
six binary options, but I don't create six subclasses; instead, I pass the
parameters into the constructor of a, "Raw," BinaryOption:

/**
* Create the system options.
*/
private void addAllOptions() {
options.add(new AlgorithmOption());
createBinaryOption(Configuration.DELETE_ORIGINAL_OPTION_NAME,
false, Configuration.MISCELLANEOUS_GROUP);
createBinaryOption(Configuration.AUTO_CLOSE_PROGRESS_OPTION_NAME,
false, Configuration.MISCELLANEOUS_GROUP);
createBinaryOption(Configuration.ALLOW_REENCRYPTION_OPTION_NAME,
false, Configuration.MISCELLANEOUS_GROUP);
createBinaryOption(Configuration.WATERMARK_OPTION_NAME,
true, Configuration.MISCELLANEOUS_GROUP);
createBinaryOption(Configuration.CHECKSUM_OPTION_NAME,
true, Configuration.MISCELLANEOUS_GROUP);
createBinaryOption(Configuration.CBC_OPTION_NAME,
true, Configuration.MISCELLANEOUS_GROUP);
Option viewOption = new ViewOption();
options.add(viewOption);
}

/**
* Creates a binary option with the given name, default value, and group
* header identity.
*
* @param name binary option name
* @param value default value
* @param groupHeaderIdentity group header identity
*/
public void createBinaryOption(String name, boolean value,
String groupHeaderIdentity) {
options.add(new BinaryOption(name, value, groupHeaderIdentity));
}

So I'd have to say, on the whole, that I tend not to have subclasses which
differ from base classes only by data.
Djikstra
claimed, until his death, that OO was unnecessary and that CS student
should be taught to formally prove their code -- there by nullifying
the need for a highly organized language like Java. Of course, his
fanaticism ignored that fact that provability of code requires a
closed system where non-determinism can't be introduced through
Network, disk io and multi-threading and, of course, silly users. To
say nothing of the time and cost to formally prove anything.

I wouldn't dream of contradicting a master such as Dijkstra, but I always
phased-out when it came to, "Predicate transformers." Some day I must look
into modal and predicate calculus to see what on earth it's all about.

I have often wondered, however, about the practicalities of program proofs.
Surely there's a circular argument in there somewhere, for how to we show
that the proof is correct?

If a proof is a page long, then I'd be happy to have an expert tell me it's
correct.

If it's fifty pages long, then I'd rather have a few experts confirm it.

If my program is one million lines long, however, how long will the proof
be? Ten thousand lines? How many experts are needed to guarantee that this
proof contains no errors?

Also, looking at a Dijkstran proof, I always find it looks like a program
itself, somehow condensed from the original. Could that proof itself be fed
into a computer and executed? If so, has the proof just, "Compressed," the
original program by some impressive factor (say 10, as above)? Can we ditch
the original and just use the executable proof?

And if we can do this, then how do we prove that the executable proof is
proven?

And can we make an executable proof of the executable proof that's an
impressively compressed factor of the (first) executable proof?
 
S

Sideswipe

I slumped in my chair when the discussion was Lambda calculus.
Assuming all programs could be proved, you rightly cite the costs of
doing so. Plus, considering the kind of "engineers" I have met in my
time, if their code didn't pass "proofing" what do you do? I mean, it
isn't like a math test where you get a question wrong, get a 'B' and
move on with life. I have found that, in software the 'good enough'
model is all people want to pay for. and then they apply the 'binary'
quality metric: Works/ doesn't work -- applying the two you get :
(Works good enough | Doesn't work good enough)
 
D

Daniel Pitts

In the example you gave I don't see enough difference to fret over it.
Perhaps with messier examples the difference would become obvious.

With constructors, the specification is positional, terse, but
confusing with a large number of parms.

In both schemes you ensure all data is provided.

I tend to like the abstract method approach. It gives flexibility to
the implementor to use either constructors, constants or complex
calculations.

If all you want is to encapsulate data, then you might consider using
an Argument object. approach.

final class MyNoLongerBaseClass {
public static final class Argument {
// necessary parameters as fields, with getters and setters
probably.
}

public MyNoLongerBaseClass(Argument argument) {
// use argument data, throw IllegalArgumentException if its not
configured properly.
}
}
From that, you might say, Oh, why don't I just make Argument a Factory
object, that can create my no longer base class objects. Well, the
answer is, you should! You can still have the constructor that
accepts the "Argument" object, but it would only be called from within
the Argument (now called Factory) class.


In this case, using the Builder pattern tends to be useful as well,
allowing chaining of method calls (think StringBuilder/ProcessBuilder)

public class MNLBBuilder {
public MNLBBuilder someProperty(String value) {
someProperty = value;
return this;
}
// ... etc...
}


MNLB mnlb = new MNLBBuilder().someProperty("Foo!").createMNLB();
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top