Interfaces without implementation are like a day without sunshine
What is the rationale for not permitting implementations in interfaces?
A: Simplicity and future proofing.
The hard requirement for interfaces (when they were conceived in AS3 at Macromedia/Adobe) was to be able to relate a class to one or more "abstract" types (as in Java). We discussed a richer idea of interfaces that would allow add implementation, etc, but were forced by design and practical concerns to choose a minimalist solution that would allow for future growth.
But how do interfaces related to traits? To quote your reference (www.iam.unibe.ch/~scg/Research/Traits): "Unlike mixins and multiple inheritance, Traits do not employ inheritance as the composition operator. Instead, Trait composition is based on a set of composition operators that are complementary to single inheritance and result in better composition properties."
They sound to me to be orthogonal, at least in form if not in function.
Jd
-----Original Message----- From: es4-discuss-admin at mozilla.org [mailto:es4-discuss-admin at mozilla.org] On Behalf Of P T Withington Sent: Thursday, August 24, 2006 10:53 AM To: es4-discuss at mozilla.org Subject: Interfaces without implementation are like a day without
sunshine
I have argued for allowing method bodies in interfaces, but I've
failed to write up a proposal. I'll give it a go unless my TG1
colleagues say that it's too late to take such a change.
Jeff, this is the generic programming pitch: often interfaces can be
implemented only in terms of other abstract methods, either in the
same interface or with type switch and calls to other interface
methods. Implementations that can optimize may, but as Tucker points
out, in Java one ends up writing the same implementation over and
over. IIRC you said something like the same thing happened with AS3
users during the evolution of the Flex SDK.
I have argued for allowing method bodies in interfaces, but I've failed to write up a proposal. I'll give it a go unless my TG1 colleagues say that it's too late to take such a change.
While we're at interfaces request I would like to ask the possibility of adding variables (and not only methods) in interfaces declarations.
P T Withington wrote:
What is the rationale for not permitting implementations in interfaces?
I don't believe there's a single "killer-reason" other than the basics:
- It would add complexity to an already complex language.
- It's not in common use from java or C#, so programmers from those backgrounds aren't likely to miss it.
Personally I don't dislike the feature, but I also think we've probably way overspent our complexity budget already, and we're past the self-imposed cutoff time for proposing broad features like this. If others are amenable to it and think we still have any wiggle room on adding things, I suppose I could be persuaded. Any takers?
Currently it feels to me like one of a dozen "would be nice" things we've passed over for lack of time / complexity budget reasons.
(Side note / question: IIRC the scala designers felt it necessary to include method renaming in trait inheritence, in order to avoid possible name collisions. I think this had something to do with preserving symmetry in the mixing of traits, rather than imposing an order. I don't quite see this as a necessary aspect of the proposed language feature, but perhaps I miss something. It seems to me that java-style interfaces can also give rise to the same sort of method-name collisions. Were they just "tidying up" a failure that can happen in java, or is the situation much worse under symmetric mixins?)
On 2006-08-24, at 14:19 EDT, Jeff Dyer wrote:
The hard requirement for interfaces (when they were conceived in
AS3 at Macromedia/Adobe) was to be able to relate a class to one or more "abstract" types (as in Java). We discussed a richer idea of
interfaces that would allow add implementation, etc, but were forced by design
and practical concerns to choose a minimalist solution that would allow
for future growth.
We have an implementation of 'traits' (composable units of behavior)
that can be built on es3. We have found them to be useful for
structuring complex systems. There are plenty of precedents for this
pattern in O-O languages, although neither Java nor C# chose to adopt
it -- perhaps for the same reasons. I'm suggesting we move beyond
the Java straight-jacket...
But how do interfaces related to traits? To quote your reference (www.iam.unibe.ch/~scg/Research/Traits): "Unlike mixins and multiple inheritance, Traits do not employ inheritance as the composition operator. Instead, Trait composition is based on a set of composition operators that are complementary to single inheritance and result in better composition properties."
While we are using the term 'trait' for our system, our
implementation is more along the lines of mix-ins (as described in
their paper www.iam.unibe.ch/~scg/Archive/Papers
Scha03aTraits.pdf). We allow a class to be composed of a base class
and any number of traits. The class is implemented by creating a
prototype linked through its [[proto]] to instances of each of the
traits and finally the base class. So our traits are order-
sensitive, they are composed by inheritance and you can override
methods in traits (and access the overridden method using super). We
have not found it necessary to adopt the 'new composition method' of
the referenced paper. Although I understand from personal experience
their concerns about mix-ins (ordering, integration, and fragility),
I'm not convinced their solution is anything more than an enforced
programming style.
We also allow state in our traits (as Nicholas requested).
From: Graydon Hoare <graydon at mozilla.com> Date: 24 August 2006 14:38:54 EDT
P T Withington wrote:
What is the rationale for not permitting implementations in
interfaces?I don't believe there's a single "killer-reason" other than the
basics:
- It would add complexity to an already complex language.
In my experience, one of the first things people ask when they learn
about interfaces is "Why can't I put (common) state and
implementation in them?" It just seems a natural thing when you
already understand classes.
- It's not in common use from java or C#, so programmers from those backgrounds aren't likely to miss it.
And they don't know what they are missing. :)
Personally I don't dislike the feature, but I also think we've
probably way overspent our complexity budget already, and we're
past the self-imposed cutoff time for proposing broad features like
this. If others are amenable to it and think we still have any
wiggle room on adding things, I suppose I could be persuaded. Any
takers?
I would be happy to assist in any way I could.
Currently it feels to me like one of a dozen "would be nice" things
we've passed over for lack of time / complexity budget reasons.(Side note / question: IIRC the scala designers felt it necessary
to include method renaming in trait inheritence, in order to avoid
possible name collisions. I think this had something to do with
preserving symmetry in the mixing of traits, rather than imposing
an order. I don't quite see this as a necessary aspect of the
proposed language feature, but perhaps I miss something. It seems
to me that java-style interfaces can also give rise to the same
sort of method-name collisions. Were they just "tidying up" a
failure that can happen in java, or is the situation much worse
under symmetric mixins?)
As I said in my reply to Jeff, mix-ins give you more rope, and with
their restrictions they are trying to limit the length of that rope.
My experience is that you can achieve the same effect with a careful
programming style, so I have not adopted those restrictions in our
implementation.
We have implemented something very similar along the mixin design described below and have found them effective for cross-cutting concerns like logging.
Michael O'Brien Mbedthis Software
On 2006-08-24, at 17:40 EDT, P T Withington wrote:
From: Graydon Hoare <graydon at mozilla.com> Date: 24 August 2006 14:38:54 EDT
P T Withington wrote:
What is the rationale for not permitting implementations in
interfaces?I don't believe there's a single "killer-reason" other than the
basics:
- It would add complexity to an already complex language.
In my experience, one of the first things people ask when they
learn about interfaces is "Why can't I put (common) state and
implementation in them?" It just seems a natural thing when you
already understand classes.
- It's not in common use from java or C#, so programmers from those backgrounds aren't likely to miss it.
And they don't know what they are missing. :)
Personally I don't dislike the feature, but I also think we've
probably way overspent our complexity budget already, and we're
past the self-imposed cutoff time for proposing broad features
like this. If others are amenable to it and think we still have
any wiggle room on adding things, I suppose I could be persuaded.
Any takers?I would be happy to assist in any way I could.
Did anything ever happen with this idea?
We are continuing to find this a useful structuring tool, enough so
that my users are complaining that 'interface' and 'implements' are
the wrong terms. They want 'interfaces with implementation' to be
called 'traits' (because that is how they intuitively think about
them) and that makes me realize that 'implements' should be
'inherits' (or something similar).
I don't like the idea of having 'interfaces' and 'traits'. That
seems overly complex. It seems to me that an interface can be
described just as well by a trait with required (abstract) methods.
We are continuing to find this a useful structuring tool, enough so
that my users are complaining that 'interface' and 'implements' are
the wrong terms. They want 'interfaces with implementation' to be
called 'traits' (because that is how they intuitively think about
them) and that makes me realize that 'implements' should be
'inherits' (or something similar).I don't like the idea of having 'interfaces' and 'traits'. That
seems overly complex. It seems to me that an interface can be
described just as well by a trait with required (abstract) methods.
True... as long as you allow multiple traits inheritance. What would be the differences with mixins then ?
On 2006-10-24, at 03:19 EDT, Nicolas Cannasse wrote:
We are continuing to find this a useful structuring tool, enough so that my users are complaining that 'interface' and 'implements' are the wrong terms. They want 'interfaces with implementation' to be called 'traits' (because that is how they intuitively think about them) and that makes me realize that 'implements' should be 'inherits' (or something similar).
I don't like the idea of having 'interfaces' and 'traits'. That seems overly complex. It seems to me that an interface can be described just as well by a trait with required (abstract) methods.
True... as long as you allow multiple traits inheritance. What would be the differences with mixins then ?
Yes, we allow multiple inheritance of traits. Our traits are the
same as mixins, it just seems that trait is a more modern term (in
line with classes implementing an ontology, as opposed to modeling
ice cream flavors).
P T Withington scripsit:
Yes, we allow multiple inheritance of traits. Our traits are the
same as mixins, it just seems that trait is a more modern term (in
line with classes implementing an ontology, as opposed to modeling
ice cream flavors).
As I understand it, "trait" implies there are no instance variables, whereas "mixin" may or may not, depending on the source tradition.
Yes, we allow multiple inheritance of traits. Our traits are the same as mixins, it just seems that trait is a more modern term
I'm pretty sure this is false. Both terms are used in current literature, and they are considered distinct. Naturally, there's a lot of variation in the usage of each, so there aren't "universal" definitions. But they aren't interchangeable, either.
According to Fisher and Reppy:
"Mixins are a mechanism designed to give many of the benefits of multiple inheritance in single-inheritance languages. There are strong similarities between traits and mixins, which are another mechanism designed to address code sharing in single-inheritance languages. The main difference between mixins and traits is that mixins force a linear order in their composition. This order avoids the complexities of the diamond property, but it makes mixins a more fragile mechanism."
[people.cs.uchicago.edu/~jhr/papers/2004/fool-traits.pdf]
Now, I have never seen traits with fields before. All the literature I've seen motivates traits as "pure units of behavior" and disallow instance variables. For example, according to Nierstrasz et al:
"Traits bear a superficial resemblance to mixins, with several important differences. Several traits can be applied to a class in a single operation, whereas mixins must be applied incrementally. Trait composition is unordered, thus avoiding problems due to linearization of mixins. Traits contain only methods, so state conflicts are avoided..."
[www.iam.unibe.ch/~scg/Archive/Papers/Duca06bTOPLASTraits.pdf]
Based on your description, it sounds like what you have implemented is order-sensitive and allows fields. So what you have sounds like mixins, not traits.
On 2006-10-24, at 10:03 EDT, Dave Herman wrote:
Yes, we allow multiple inheritance of traits. Our traits are the
same as mixins, it just seems that trait is a more modern termI'm pretty sure this is false. Both terms are used in current
literature, and they are considered distinct. Naturally, there's a
lot of variation in the usage of each, so there aren't "universal"
definitions. But they aren't interchangeable, either.According to Fisher and Reppy:
"Mixins are a mechanism designed to give many of the benefits of
multiple inheritance in single-inheritance languages. There are
strong similarities between traits and mixins, which are another
mechanism designed to address code sharing in single-inheritance
languages. The main difference between mixins and traits is that
mixins force a linear order in their composition. This order avoids
the complexities of the diamond property, but it makes mixins a
more fragile mechanism."[people.cs.uchicago.edu/~jhr/papers/2004/fool-traits.pdf]
Now, I have never seen traits with fields before. All the
literature I've seen motivates traits as "pure units of behavior"
and disallow instance variables. For example, according to
Nierstrasz et al:"Traits bear a superficial resemblance to mixins, with several
important differences. Several traits can be applied to a class in
a single operation, whereas mixins must be applied incrementally.
Trait composition is unordered, thus avoiding problems due to
linearization of mixins. Traits contain only methods, so state
conflicts are avoided..."[www.iam.unibe.ch/~scg/Archive/Papers/Duca06bTOPLASTraits.pdf]
Based on your description, it sounds like what you have implemented
is order-sensitive and allows fields. So what you have sounds like
mixins, not traits.
I admit to not being aware that 'trait' had been staked out as you
describe above. We have been using the term more in line with the
dictionary definition. If trait is defined as not permitting state
or overriding, then, yes, we have implemented mixins. Using the
definitions you cite, interfaces << traits << mixins. Traits remove
state (and in some cases overriding) from mixins, interfaces remove
behavior from traits. Or, looking at it another way, traits and
interfaces take power away from the programmer in the belief that the
programmer will only hurt themselves. Where does es4 want to stand?
On Oct 24, 2006, at 11:35 AM, P T Withington wrote:
Using the definitions you cite, interfaces << traits << mixins.
Traits remove state (and in some cases overriding) from mixins,
interfaces remove behavior from traits. Or, looking at it another
way, traits and interfaces take power away from the programmer in
the belief that the programmer will only hurt themselves. Where
does es4 want to stand?
If you put it that way... :-P.
We are past the point where a proposal to allow var or method body
declarations in interfaces could "squeak by". I regret not pushing
this earlier; it was discussed, but no one including me put together
a proposal. We questioned the wisdom of making interfaces look like
very different animals from their namesakes in nearby languages. But
that was not the reason we didn't do mixins. Really, we had and
still have a lot to do, under a short schedule.
Extending interface as discussed is possible; the obvious extension
is reserved syntax for which we could provide meaning in the future.
Implementations might take chances providing mixins as an extension
under this syntax. Comments?
overriding, then, yes, we have implemented mixins. Using the
definitions you cite, interfaces << traits << mixins. Traits remove
state (and in some cases overriding) from mixins, interfaces remove
behavior from traits. Or, looking at it another way, traits and
No, traits and mixins are different language features with different designs and trade-offs. It's not just about instance variables. Traits can be combined in any order, and mixins are combined in a programmer-specified order. This means that traits buy you convenience that mixins don't have: they abstract over the inheritance chain. Mixins, OTOH, avoid diamond import problems by forcing the programmer to create a total order on composition.
interfaces take power away from the programmer in the belief that the
programmer will only hurt themselves. Where does es4 want to stand?
This false dichotomy is trotted out all too often. Limiting the expressive power of a programming construct has many purposes, and "protecting novices" need not have anything to do with it.
But that's not even the issue: traits and mixins each have relative pros and cons. It's an active research topic, and the final word has not yet been written. Unfortunately, we're on a schedule and it looks like this one is just out of scope.
On 2006-10-24, at 13:03 EDT, Dave Herman wrote:
overriding, then, yes, we have implemented mixins. Using the
definitions you cite, interfaces << traits << mixins. Traits
remove state (and in some cases overriding) from mixins,
interfaces remove behavior from traits. Or, looking at it
another way, traits andNo, traits and mixins are different language features with
different designs and trade-offs. It's not just about instance
variables. Traits can be combined in any order, and mixins are
combined in a programmer-specified order. This means that traits
buy you convenience that mixins don't have: they abstract over the
inheritance chain. Mixins, OTOH, avoid diamond import problems by
forcing the programmer to create a total order on composition.
Perhaps I am mistaken, but it seemed to me the reason that traits can
be combined in any order is because traits explicitly disallow
conflicting properties. (Either they are disallowed altogether, or
they have to be renamed.) This is what I meant by 'traits remove
overriding from mixins'.
interfaces take power away from the programmer in the belief that
the programmer will only hurt themselves. Where does es4 want to
stand?This false dichotomy is trotted out all too often. Limiting the
expressive power of a programming construct has many purposes, and
"protecting novices" need not have anything to do with it.
My reading of Schärli, et al. is that traits are explicitly designed
to remove features of multiple-inheritance and mixins that are deemed
dangerous (because they lead to ambiguities and fragility). Am I
mistaken there also?
But that's not even the issue: traits and mixins each have relative
pros and cons. It's an active research topic, and the final word
has not yet been written. Unfortunately, we're on a schedule and it
looks like this one is just out of scope.
I admit that I am out of the academic loop here. If you can point me
to additional reading, I'd appreciate it.
Perhaps I am mistaken, but it seemed to me the reason that traits can
be combined in any order is because traits explicitly disallow
conflicting properties. (Either they are disallowed altogether, or
they have to be renamed.) This is what I meant by 'traits remove
overriding from mixins'.
That's my understanding as well, although I'm not familiar with stateful traits. The 2006 paper by Flatt et al (below) might have something like that, but I haven't read it.
My reading of Schärli, et al. is that traits are explicitly designed to remove features of multiple-inheritance and mixins that are deemed
dangerous (because they lead to ambiguities and fragility). Am I
mistaken there also?
I think that's accurate, but I'm not an expert. But I believe it's an oversimplification to claim "interfaces << traits << mixins". In fact, it's not obvious to me that these features are mutually exclusive.
I admit that I am out of the academic loop here. If you can point me
to additional reading, I'd appreciate it.
I'm not really in the loop, either. My point is just that mixins and traits are different beasts, and esp. traits are pretty new territory.
The publications I know of are:
Gilad Bracha's work: bracha.org/Site/Papers.html
John Reppy's work: people.cs.uchicago.edu/~jhr/papers/object.html
Flatt, Findler, Felleisen, APLAS 2006 Scheme with Classes, Mixins, and Traits www.cs.utah.edu/plt/publications/aplas06-fff.pdf
Findler, Flatt, ICFP 1998 Modular Object-Oriented Programming with Units and Mixins www.ccs.neu.edu/scheme/pubs/icfp98-ff.pdf
Flatt, Krishnamurthi, Felleisen 1999 A Programmer's Reduction Semantics for Classes and Mixins www.ccs.neu.edu/scheme/pubs/tr97-293.pdf
Scala: scala.epfl.ch/intro/traits.html, scala.epfl.ch/docu/related.html
Fortress: research.sun.com/projects/plrg
And then the link you sent: www.iam.unibe.ch/~scg/Research/Traits
What is the rationale for not permitting implementations in
interfaces? One of my primary gripes with interface in Java is that
typically means you are going to have to write the same
implementations over and over and over, with the risk that one of
your implementations may skew.
Why not allow implementation in interfaces as a way to package a unit
of functionality that can be shared by a number of classes?
(There is a good overview of this pattern at www.iam.unibe.ch ~scg/Research/Traits/. Note that the 'traits' here are different
from the ES4 use of trait in the specification.)