Abstract functions in child classes

Adam Adam at Anizi.com
Fri Dec 2 13:13:45 PST 2011


> You're being a bit dramatic, no?  The code didn't compile, the
compiler
> caught it, and you have invented this theoretical case (which did
*not*
> occur) to try and make your point.  I don't deny that requiring
'abstract'
> has some value, but what I question is how much is that value?
Since a
> reasonable developer uses tests (or uses the code in question
himself) and
> will end up instantiating any concrete class during testing (or
usage),
> I'd say the value is pretty close to zero (not zero, but very
close).


A bit, but the point I've been trying to make is that it's an on-
instance usage, rather than a compile-time check (Timon Gehr has
since demonstrated a case as to why this could be valid), and the
response I keep getting back is "you should be doing testing," when
my point is that I shouldn't be having to test the concreteness /
abstractness of a class. The theoretical case was to demonstrate
that this could be an issue. Is the value minimal? I'd argue
otherwise, but, that's probably tangential, so, moving on...

> But let's assume for a moment that it's standard practice to avoid
unit
> testing.  The error that occurs is not a sneaky silent one, it is
a loud
> compiler error.  The only risk is that the user of your library
finds it
> before you do, because you didn't test, but it still doesn't
compile.  Any
> time an error occurs at compile time, it is a win, since the user
didn't
> accidentally use something incorrectly.  So here's the solution --
use
> tests.  In my opinion, breaking any existing code to add this
requirement
> is unacceptable.

My issue here was (again, past tense because of Timon's example)
that the error occurs on usage rather than compilation, even when
that's quite outside of what I'd expect or want. It seemed to be at
odds with a lot of other D's semantic decisions, particularly with
respect to other transitive types and things liked synchronized, or
even shared (which I'd probably describe as closer to infectious
than transitive). What I've been asking is *why* this isn't a
requirement, and except for Timon, the only answers I'd gotten were
"because it would break existing code" (ok, but not an explanation
as to why it was DESIGNED that way in the first place), because it
was minimally inconvenient (even if more explicit, like other D
parts), or that to even raise the question just suggested I was a
bad programmer and that these sorts of definitions should be tested.

The crux of my issue with the testing argument is that, rather than
having the compiler be able to verify that a concrete class is, in
fact, concrete, I'm being asked to verify via unittest or otherwise
that my class is, in fact, concrete, rather than abstract. On a
related note, would you argue that there is any value to be gained
from *allowing* a class to be marked as concrete? That is,

concrete Child : Parent {}

*must* implement all abstract members? *I'd* use it, because if
nothing else, it provides a guarantee to users or inheritors of my
class as to its intended type (rather than using an implied
definition), even if the base type changes.

> If the base class changes in any way, your derived class may not
compile.
> It may break in subtle ways that *do* compile.  If you are going
to insist
> on not testing your code after the base class changes, well, then
I guess
> you will have to get used to it failing.  Just be thankful if you
get a
> compiler error instead of a latent runtime error.

And, again, my issue here is that the issue isn't caught until
instantiation, and is again relying on me to test the definition of
my class (rather than its usage). But, I'm going in circles, and I
just kept getting pointed back to the need to test my code (which
I've never contested). It just seemed particularly odd (and
insulting, given the actual statements) that the implication was
that I needed to test the abstractness or non-abstractness of my
code. Of *course* I'm going to test instantiation if I intend to
instantiate it, and of *course* I'd find it there, but my point was
never to ship anything untested to anyone. I just don't like having
this sort of assertion occur in a unittest rather than the actual
class definition (where, again, I think it belongs).

Somewhat related, but I know of companies that have separate
developers provide test cases than the implementers, and it's
perfectly possible (and valid) in D for the implementer to hand off
a finished definition of a concrete class only to discover its
problematic with respect to a unittest. Or, to reaaaally stretch
pointless hypothetical arguments, in using some sort of dynamic
allocation of a class (Object.factory) rather than an explicit name
for my concrete class. Maybe using some sort of mechanism to auto-
generate unittests for any given implementation of an abstract,
rather than on an implementation-by-implementation basis.

Anyway, I have my answer, and I know that D *does* have a reason for
this implicitism.


More information about the Digitalmars-d-learn mailing list