In a message dated Fri, 25 Aug 2006, Mark J. Reed writes:
On 8/25/06, Trey Harris <[EMAIL PROTECTED]> wrote:
> subclasses can remove functionality as well as adding it
Can someone suggest some reading I can do to understand how that works?
I can't wrap my head around the idea of subclasses removing functionality.
Why not? Is it any weirder than simply changing that functionality
beyond recognition?
If "changing that functionality beyond recognition" means changing its
external behavior (as opposed to its internal behavior) so that it acts
differently from what the superclass had promised to do, then no, it's not
any weirder--but I can't figure out how the contract would work, either.
To extend the "contract" analogy, if I lease you a house, I may allow you
to sublease the house, and I may even agree to take my rent directly from
the sublessee rather than from you. But the sublessee can't just say to
me, "yeah, so, I'm going to pay you 1000 yen, not 1000 dollars," and
expect me to just put up with it or work around the missing money. I made
assumptions based on the original contract. If the sublessee says he wants
to pay me more or more promptly or in cash under the table, great. If he
wants to listen to opera in the evenings instead of of watching TV, that's
internal behavior having nothing to do with our contract and I don't care.
The changes have to be either in my favor or irrelevant to the contract.
Otherwise, I'm going to demand we renegotiate--in other words, that you
don't pretend to be a superclass whose behavior you're not willing to
emulate, so that when I see you I can treat you as what you are, not what
you're pretending to be.
"isa" means "is a". It doesn't mean "is roughly of a class analogous to".
You can always fake removing functionality even if the language
doesn't actually support it. Consider:
class Super { method something {...} }
class Sub is Super { method something { throw new MissingMethodException; } }
or whatever that ends up looking like.
In Ruby and C++, a subclass can make a method private that is public
in its superclass, effectively removing it. (Java disallows such
shenanigans).
But why would you want to, just because "ConstArray isa Array, not the
other way around" just feels right? "Pluto isa Planet" feels right too,
but one can't construct a reasonable definition that doesn't pull things
in that you don't want to consider Planets.
Remember, one of the goals of Perl 6 is to make it more friendly to very
large software projects. "Java disallows such shenanigans" is one example
of precisely why Java has become so popular for large projects. (The
exception-throwing example is clearly, well, an exception, and you can
always do that.)
When software gets large, you need to be able to impose some constraints
on behavior. Maybe this is a stricture or something. In any case, I'm
not trying to make a ideological argument here. I don't care if you can
remove functionality or add constraints if that helps me get my job done
(I'm just skeptical that it will).
I just want to think about the DBC features of Perl 6, and I don't know
how they could work in the context of loosening contracts in subclasses,
and I'd like somebody to point me to how, that's all. Design-by-Contract
is all about formal definitions.
Does this mean you can't [...] expect foo($obj) to work
Of course you can expect foo($obj) to work. It might not, if the
subclass definition does something weird, but that's always the case
whether "removing functionality" is on the table or not, and it's no
reason to change your reasonable expectations. You can be paranoid
about it if you want, but it's not a very Perlish form of paranoia.
(Yes, there are Perlish forms of paranoia. Taintedness checking, for
instance...)
When I said "expect it to work", that was shorthand for "it *will* work,
in the absence of a bug". That's what DBC is all about--that one can
program based on the expectations of the contract, and you don't have to
write error-catching code every single time you use an object's exported
functionality.
I'll agree that DBC isn't very Perlish, in much the same way that strict
was not very Perlish in Perl 5 (for at least the first five years of its
existence, and probably even till today). But in Perl 6 strict is the
default, so by definition now Perlish. :-)
If DBC is in the language, then some people will use it, most people won't
because they don't like the inconvenience, and over time if it actually
results in more solid software, more people will choose to adopt it (like
strict).
But in order to allow that choice, the language has to impose some
groundrules for everyone. strict couldn't exist in Perl 5 if lexicals
could autovivify. And--*by my understanding of DBC*--subclasses can't
remove promised functionality or impose surprising constraints. So a)
Perl 6 can't support DBC, contrary to the Synopses, b) you can't remove
functionality or impose new constraints in subclasses, or c) my
understanding of DBC is incorrect.
Trey