atom feed19 messages in Mixin inheritance
FromSent OnAttachments
Brian GoetzMar 13, 2009 11:50 am 
Michael AzziMar 13, 2009 12:43 pm 
Brian GoetzMar 13, 2009 1:20 pm 
Michael AzziMar 13, 2009 1:42 pm 
Weiqi GaoMar 14, 2009 6:24 am 
Kim TopleyMar 14, 2009 7:40 am 
Robert FieldMar 15, 2009 12:53 pm 
Brian GoetzMar 16, 2009 11:18 am 
Brian GoetzMar 16, 2009 11:19 am 
Kim TopleyMar 16, 2009 12:21 pm 
Weiqi GaoMar 16, 2009 7:37 pm 
Brian GoetzMar 18, 2009 11:32 am 
Michael AzziMar 18, 2009 11:56 am 
Weiqi GaoMar 18, 2009 7:09 pm 
Brian GoetzMar 20, 2009 9:11 pm 
Brian GoetzMar 20, 2009 9:12 pm 
Brian GoetzMar 20, 2009 9:18 pm 
Weiqi GaoMay 3, 2009 7:31 pm 
Brian GoetzMay 3, 2009 7:52 pm 
Subject:Re: Mixin inheritance
From:Weiqi Gao (
Date:May 3, 2009 7:31:36 pm

Compiler team,

I'm revisiting the mixin issue raised in the quoted email. (also see near the end of this MarkMail thread:

It seems that this issue was logged as

and resolved as build: commit message: [marina-master:4795]

However, the effect of the fix is reversed in build: commit message: [marina-master:4868]

Is this a temporary or a permanent state of affairs?


Michael Azzi wrote:

Maybe this is a stupid question, but I'll ask it anyway just out of curiosity. Why is it that we can disambiguate the mixed in functions such as the play() function below, but not the overlapping mixed in vars? Any particular reason for the different treatments.

I was thinking along the same lines when I asked the question. It seems that the current Mercurial HEAD *does* allow disambiguation of vars the way I described:

[weiqi@gao]$ cat foo.fx mixin class Football { var count:Integer = 1024 on replace { println("In Football: count={count}."); }

function play() { println("Football playing"); count++; } }

mixin class Video { var count:Integer = 2048 on replace { println("In Video: count={count}."); }

function play() { println("Video playing"); count++; } }

class FootballVideo extends Football, Video { var countInFootball = bind (this as Football).count; var countInVideo = bind (this as Video).count;

function playFootball() {; }

function playVideo() {; } }

var o = FootballVideo {}; o.playFootball(); o.playVideo(); o.playFootball(); println("o.countInFootball={o.countInFootball}."); println("o.countInVideo={o.countInVideo}.");

[weiqi@gao]$ javafxc foo.fx [weiqi@gao]$ javafx foo In Football: count=1024. In Video: count=2048. Football playing In Football: count=1025. Video playing In Video: count=2049. Football playing In Football: count=1026. o.countInFootball=1026. o.countInVideo=2049.

Since the mixin mechanism does not attempt to resolve conflicts between multiple mixins on the same extends line, how the language treats it does not matter much for the envisioned normal use of the mixin feature.

Although on a purely logical level, I like the current behavior more because of its symmetry and reasonableness. In a sense, the two mixins Football and Video still *work* in spite of the conflict. Had the compiler behaved as Brian described, *neither* would work.

Another question I had regards the additive nature of on replace triggers on such conflicting vars. Should the on replace trigger for Video.count fire? It did fire in the current implementation.

Also, on a separate note, would you see any value in using "mixin" instead of "extends" when mixing in mixins, and only use "extends" for extending real classes? The one advantage that I see, is that by only looking at the class declaration I can tell right there which are the mixins, and which is the class. Plus, we are not adding any new keywords to support this.

What about Java interfaces?

--- On Wed, 3/18/09, Brian Goetz <Bria@Sun.COM> wrote:

From: Brian Goetz <Bria@Sun.COM> Subject: Re: Mixin inheritance To: Date: Wednesday, March 18, 2009, 2:32 PM Not quite. While both of those expressions are legal, they are in fact references to the *same* variable. There is not a separate count variable for Video and for Football.

Weiqi Gao wrote:

Thanks Brian,

It all make sense.

It seems that even though a simple reference to count

while inside the body of FootballVideo refers to Football's count, I can get at Video's count through the expression

(this as Video).count

and its value is independent of the simple reference of count, which is equal to (this as Football).count

-- Weiqi Gao

There is only one count variable.

Mixing is *not* multiple inheritance; it doesn't

inherit a count from both Football and Video. Instead, what both Football and Video say is "The mixee class must have an int variable called count; if one does not exist, add one at mix time." Mixin fields are mixed in in the order the mixins are specified, so what happens is:

- FootballVideo wants to mixin Football - It doesn't have a 'count' var, so it gets one - Then it wants to mix in Video - It already has a count field, so nothing else happens. In your example, there is a real conflict over

"count". The mixin mechanism does not attempt to resolve that.

The play() method can be disambiguated by calling or Weiqi Gao wrote:

How will the accidental variable name

conflicts in unrelated mixin classes be handled? In the following example:

public mixin class Football { public var count:Integer = 0; public function play() {

println("Football playing");

count++; } }

public mixin class Video { public var count:Integer = 0; public function play() { println("Video playing"); count++; } }

public class FootballVideo extends Football, Video { public override function play() {

println("FootballVideo playing");;; } }

there doesn't seem a way to get at the count

variable from either Football or Video.