Post by 'Gilad Bracha' via Dart MiscThe key misunderstanding seems to be that people think they are mixing in
a class. What you actually mix-in is a mixin. The mixin is what a class
adds to its superclass - intuitively, the stuff between the curly braces in
the class declaration.
A mixin is really a very special kind of function, one that takes a
superclass S and returns a subclass of S. A class is always associated
with a mixin. You could think of class Foo extends Bar { ...} as
FooMixin(S) { return class extends S {...}} // illegal in Dart of course
along with
var Foo = FooMixin(Bar);
The *with* notation is really a syntax for applying these mixin functions.
class C extends S with M1 with M2
is really
class C extends (M2.mixin(M1.mixin(S)))
where M1 and M2 are classes, and X.mixin denotes the mixin function
implicitly induced by class X. Having such a special notation for mixins
may or may not help but is certainly more verbose, which nobody likes.
That is one way to interpret the language's semantics, but it's not the
only way that is consistent with its visible behavior. The intuition that
users seem to have is that the name of a class in a with clause refers to
the mixin composition of it and all of its superclasses (except Object),
and not just the class's own mixin. Up until this new proposal, those two
concepts were indistinguishable since any class used as a mixin had no
non-Object superclasses. Now that we're relaxing that, we have to decide
what a class's name should refer to.
The clear feedback we're getting is that having it refer to *only* the
class's mixin is counter-intuitive. We could just as easily define:
class M1Base {}
class M1 extends M1Base {}
class M2Base {}
class M2 extends M2Base {}
class C extends S with M1, M2
C > M2 M2Base M1 M1Base S
as really:
class C extends (M2.mixin(M2Base.mixin(M1.mixin(M1Base.mixin(S)))))
Or, in other words, define <class>.supercompose as the mixin composition of
the class's mixin and all of its superclasses' *sans* Object, and then
define with as really:
class C extends (M2.supercompose(M1.supercompose(S)))
Once you understand the semantics, you realize that mixing in the entire
Post by 'Gilad Bracha' via Dart Miscinheritance chain only makes sense via mixin composition, just as applying
a series of functions must be made explicit via function composition.
Sure, but in practice, people tend wrap up composition inside a named
function.
Regardless of whether mixin composition should have an explicit syntax on
its own, we have to decide what a class name refers to inside a with
clause. It can't refer to the class itself because, as you said, a class
isn't a mixin. One option is to have it be the class's mixin, but I think
we have good usability evidence that that isn't the right choice if we
start allowing with clauses to contain classes that have non-Object
superclasses.
In the end, software engineering isn't always trivial. Sometimes one has to
There may be valid reasons to prefer one interpretation over the other, or
perhaps we need syntax to let the user express either. But, either way, it
is not *ignorance* on the part of our users that they intuit the latter
while you had in mind the former when *up until now Dart behaved such that
both are equally valid interpretations.*
- bob
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.