contravariant argument types: wanna?
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Wed Sep 23 11:01:59 PDT 2009
Jeremie Pelletier wrote:
> Have you read my other post in this thread where I show an actual
> example of covariant arguments from my display interface, my I/O
> interfaces also use covariant arguments although they're more friendly
> to generic interface parameters.
I did. I don't have enough information to comment on the design, but at
the end of the day, statically-typed OO designs should be for families
that have many commonalities and few differences. As such, access to the
interface should be everything needed for carrying out most tasks.
Maintaining two parallel hierarchies in which each of them must cast
around from the least capable to the concrete one is, I think, a design
due for some improvement.
A derived class does not "extend" its base class. It specializes it,
because the base class represents an archetype for a variety of types,
including the derived class but much larger. So a Mammal doesn't quite
"extend" Animal because Animal includes all animals, mammals and
reptiles and whatever. If anything, Mammal narrows the inheritance cone
from under Animal. Indeed Mammal does add state, but Animal should not
be considered holding its state; it's holding its own state plus the
unrealized state of any class inheriting from it.
Unfortunately many designers today are blocked in the "inheritance
extends" view of things. They define a base class or interface first
with a narrow set of primitives, and then they "extend" it by defining
new methods, which works exactly against object orientation. Every new
method that's not in the parent class is an invitation for casting and
against reuse and genericity. Ironically, Java put that characterization
straight in the language, furthering the legitimacy of bad designs. A
good OO design defines abstract yet _capable_ generic interfaces that
suffice for achieving complex goals, and then implement them in concrete
classes. Very rarely if ever should a piece of code know the exact
implementation of an interface.
I am considering discussing all of the above in detail in TDPL, but I am
afraid that some refugees from other languages will be shocked.
> The point is, you see covariance all the time in interface programming
> when implementations expect an interface argument to be an object from
> that same implementation. As soon as you use an abstract factory to let
> the world use some implementation without being aware of which one it
> is, you're bound to see covariance at some point. Most people just code
> it explicitly, the mozilla code is *full* of explicit covariant
> interface requests.
>
> While they may not be sound, its still a scenario you're gonna come
> across sooner or later, and a scenario which involves lots of similar
> boilerplate that can easily be generated by the compiler.
The "capability cast" scenario could occur now and then, but if it's too
frequent it reflect a problem in the design, not in the language
implementing it.
Andrei
More information about the Digitalmars-d
mailing list