designing a java extension with mixins

27
Designing a Java Extension with Mixins Presented by: Yoav Gur http://www.disi.unige.it/person/L agorioG/jam/

Upload: pekelo

Post on 05-Jan-2016

40 views

Category:

Documents


1 download

DESCRIPTION

Jam. Designing a Java Extension with Mixins. http://www.disi.unige.it/person/LagorioG/jam/. Presented by: Yoav Gur. Definition. A mixin is a parametric heir class, that can be instantiated on different classes to create different heirs, that extends those classes - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Designing a Java Extension with Mixins

Designing a Java Extension with Mixins

Presented by: Yoav Gur

http://www.disi.unige.it/person/LagorioG/jam/

Page 2: Designing a Java Extension with Mixins

Definition

A mixin is a parametric heir class, that can

be instantiated on different classes to create

different heirs, that extends those classes

using the features defined in the mixin.

Every mixin is applicable only on a predefined family of parent classes, which satisfy certain requirements defined by the mixin.

Page 3: Designing a Java Extension with Mixins

“Designing a Java Extension…”

Must correspond to Java principles:

• Object oriented.

• Strongly typed.

• Allows overriding, overloading, and hiding.

• Dynamic binding of non-static methods.

• Static binding of fields and static methods.

Page 4: Designing a Java Extension with Mixins

“…with Mixins”

A new notation must be added:

• A way to declare a mixin.

• A way to state requirements from the parent class to be extended.

• Presents two new preserved words: “mixin” and “inherited”.

Page 5: Designing a Java Extension with Mixins

A simple example – mixin declaration

• Use the new preserved word “mixin” to declare a new mixin.

• Use the new preserved word “inherited” to state requirements from the parent class.

• A legal parent class must supply the stated fields, and the exact stated methods.

• No constructors.

can you think on a different logical requirements in regards to methods?

mixin Undo{inherited String getText();inherited void setText(String s);String lastText;void setText(String s){

lastText = getText();super.setText(s);

}void undo(){

setText(lastText);}

}

Page 6: Designing a Java Extension with Mixins

A simple example – Mixin instantiation

• We will call “mixin instance” a class obtained by instantiating a mixin (not to be confused with an instance of a class).

• Constructors of the new mixin instance are to be defined in the curly brackets.

class Textbox extends Component{String text;…String getText() { … }void setText(String s) { … }

}

class TextboxWithUndo = Undo extends Textbox { }

Page 7: Designing a Java Extension with Mixins

Semantics – “The copy principle”

“A class obtained by instansiating a mixin M on a

parent class P should have the same behavior as a

usual heir of P whose body contains a copy of all

components defined in M”

Intuition:

It is possible to get the same effect of mixin instantiation in pure Java

by defining many “hand-made” subclasses, which extend different

parent classes and have the exact same body.

Page 8: Designing a Java Extension with Mixins

A mixin is a type

• So far, the presented extension allows avoiding code duplication by using mixins.

• But that’s not all: a mixin can be used as a type, and a mixin instance is a subtype of both the mixin and the parent class on which it has been instantiated.

Page 9: Designing a Java Extension with Mixins

About mixin as a type

• A mixin type M can be used in any place that a interface type can be used.

• It is possible to access inherited fields and invoke inherited methods on expressions of mixin types.

• A mixin can implement interfaces in exactly the same way a class does.

• An heir class, H = M extends P, is a subtype of both M and P, and therefore is implicitly convertible to both.

• As in interface types, a mixin type cannot be used for creating objects.

Page 10: Designing a Java Extension with Mixins

Static members

• A semantic question rises: should we count the number of inc() invoked from all mixin instances of M, or keep a separate counter for each mixin instance?

• “The copy principle” dictates the latter.

• Therefore, static members are not a part of the mixin type.

(i.e. H.inc() is legal, but M.inc() is not legal).

mixin M {static void inc() { counter++ ;}static int counter = 0;

}

class H = M extends Object { }

Page 11: Designing a Java Extension with Mixins

Abstract methods

• Declaring an inherited abstract method is a request for the parent class to declare, but not necessarily to implement, the method.

• The parent class can implement the method.• It is also possible to redefine a method as abstract:

mixin M {inherited abstract void f();

}

mixin M {inherited void f();abstract void f();

}

Page 12: Designing a Java Extension with Mixins

Ambiguity in field accesses in case of double mixin instantiation

• Which f will be 7?

• The copy principle doesn’t help here

• Arbitrary solution that corresponds the most to “the spirit of Java”: The field which is selected is determined by the dynamic type of m.

• Still: Jam compiler will produce a warning to make the user aware that field accesses through a reference of the mixin type have nonobvious semantics.

mixin M { int f; }class Once = M extends Base{}class Twice = M extends Once{}

class Test {void test(){

Once o = new Twice();foo(o);

}void foo(M m) { m.f = 7; }

}

class Twice has two fields named

f, one is hidden

by the other.

Page 13: Designing a Java Extension with Mixins

Translation into Java – Jam’s implementation

• inherited declarations in mixin M are translated to an interface Parent$M.

• A mixin M is translated to an interface M that extends Parent$M, with getters & setters for M’s fields.

• Access to M’s fields is translated to a call to the appropriate getter/setter.

– Corresponds to dynamic binding of M’s fields in case of double instantiation.

• “class H = M extends P {}” is translated to “class H extends P implements M {…}”

• M’s body is copied to H’s body, according to the copy principle.

• Code duplication is only “delayed” until the translation to Java.

Page 14: Designing a Java Extension with Mixins

Implicit Constraints• All constraints we saw so far were positive:

– What must exist (abstract is an exception)

• There are also, implicit, negative specification– What must not be in the base class

• Three implicit such constraints:– Unexpected overriding: overriding a method which was not

declared as inherited– Illegal overriding: not a full signature match– Ambiguous overloading: (roughly) a method in the mixin

overloads a method in the base, which may cause surprises to the user

• Like positive constraints, depend only on mixin type (independent of implementation).– A modification of a method body does not affect instantiation

correctness.

Page 15: Designing a Java Extension with Mixins

Unexpected Overriding

• Mixin M, method mM, class C, method mC

• The names of mM and mC are identical.• Signatures are identical • However, M does not declare mC as inherited.• Example: mixin Undo on a class with a void undo()

• A Correct Java class, not what you expect.• JAM produces an error message at

– instantiation time

• Note: Unexpected overriding of fields and static methods is allowed!

Page 16: Designing a Java Extension with Mixins

Illegal Overriding

• Mixin M, method mM, class C, method mC

• The names of mM and mC are identical.• Signatures are almost identical (same

argument types), but:– Different return type– Different classification (static/instance)– Different throws clause

• JAM produces an error message at– instantiation time

Page 17: Designing a Java Extension with Mixins

Overloading and Ambiguity(for now, forget about mixins)

• Overloading: class C has several implementations of method m, all with different signature.

• Ambiguity: more than one signature matches a call site.– Which version should the compiler use for

• (new C()).m(…)

• Java has built-in rules for ambiguity resolution.• There are cases when these rules fail.class A {} class B extends A{}

class C {void m(B b) {}void m(A a) {}

}

(new C()).m(new B())

m(B b) will be chose

n

class C {void m(Integer i) {}void m(String s) {}

}

(new C()).m(null)No

Solution

Page 18: Designing a Java Extension with Mixins

Java Ambiguity Resolution

• Tournament• <C,P1,…Pn> Characterizes a candidate

– C: The declaring class– Pi: The ith parameter type

• <C1,P11,…Pn1> vs. <C2,P12,,…Pn2>– Signs:

• C1 ≥ C2 ≡ “C1 is equally or more specific then C2”• Pi1 ≥ Pi2 ≡ “P1 is equally or more specific then P2”

– <C1,P11,P21,…Pn1> will win iff:• C1 ≥ C2 AND P11 ≥ P12 AND … AND Pn1 ≥ Pn2

• If there is more then one champion:– No Solution

Page 19: Designing a Java Extension with Mixins

Ambiguous Overloading with Mixins – Motivation (1)

• Mixin M, method mM, class C, method mC, mixin instance H– mM may be an inherited method

• An overloading relation between mM and mC

• M’s author, do not know that it will be attached to C, and therefore is unaware of the overloading conflict.

• Jam’s compiler can not know M’s dynamic type at compilation time.– Also unaware of overloading between mM and mC

Page 20: Designing a Java Extension with Mixins

Ambiguous Overloading with Mixins - Motivation (2)

mC is inherited mC is not inherited

Call Site

inside M

• M is not legal

• Error on call site inside M

• M is legal, H is not legal

• Error on generated Java code of H

Call Site outside M

• M is legal, H is legal

• Error on call site outside M

• M is legal, H is legal

• Error on generated Java code outside M

• Assume:– Overloading relation between mM and mC

– Ambiguous call to mM()• either from inside M (this.mM())• or from outside M (H.mM())

• Without the third constraint:

Page 21: Designing a Java Extension with Mixins

Ambiguous Overloading with Mixins

• Solution - Third implicit constraint:– mC is not inherited

– The names of mM and mC are identical

– Signatures are interfering• Difference is only in parameter type of reference types

– JAM produces an error message at• instantiation time

• Assuming {boolean,int} are the only primitive types, avoids ambiguities entirely.

• Otherwise, interfering should be redefined.

Page 22: Designing a Java Extension with Mixins

What’s the Type of this?mixin M {

void g() {int i = A.f(this);

}}

class H = M extends Object{}

class H {void g() {

int i = A.f(this); }

}

mixin M

class H

However, by the copy principle (which is also the way JAM is implemented)…

Problem: the type of “this” dictates ambiguity resolution rulesSolution: “this” has type M, but it cannot be passed as an argument!It can be assigned to other variables, of explicit type M.

Page 23: Designing a Java Extension with Mixins

Limitations

• No parametric notation for the parent and heir.• Some code can’t be generated by mixins:

class P {}class H extends P {

public H m() {return this;}}

class P {}class H extends P {

public P m() {return this;}}

class P {}mixin M {

public M m() {return this;}}class H = M extends P{}

• Adding such a notation would prevent using mixin as a type.

Page 24: Designing a Java Extension with Mixins

Translation into Java – Jam’s implementation (reminder)

• inherited declarations in mixin M are translated to an interface Parent$M.

• A mixin M is translated to an interface M that extends Parent$M, with getters & setters for M’s fields.

• Access to M’s fields is translated to a call to the appropriate getter/setter.

– Corresponds to dynamic binding of M’s fields in case of double instantiation.

• “class H = M extends P {}” is translated to “class H extends P implements M {…}”

• M’s body is copied to H’s body, according to the copy principle.

• Code duplication is only “delayed” until the translation to Java.

Page 25: Designing a Java Extension with Mixins

Alternative translation into Java homogeneous implementation

• A mixin M is translated the same way as in Jam’s implementation.

• M’s methods which are not getters/setters are translated to static methods of a new class “BodyM”, with an additional parameter “M This”.

• Those methods in H are implemented by calls to the corresponding methods in BodyM, with “this” as the additional parameter.

• Some code duplication is avoided.

• The downside: what about private/protected members in M?Getters & setters must become public for BodyM to be able to use them. Other methods must become public in BodyM for H to be able to use them.

Page 26: Designing a Java Extension with Mixins

Conclusion (1)

• The two design principles of Jam: – The copy principle– A mixin name can be used as a type.

• A mixin instance is a subtype of both the mixin and the parent class.

• Static members are not a part of the mixin type.

• In case of double mixin instantiation, field accesses through a reference of the mixin type use dynamic binding.

Page 27: Designing a Java Extension with Mixins

Conclusion (2)• Overloading resolution corresponds to Java’s “more specific” rule.

• Instantiation is illegal in cases of unexpected overriding, illegal overriding, or ambiguous overloading.

• Some legal instantiations may still generate an erroneous Java class.

• use of “this” as argument inside a mixin is forbidden.

• No parametric notation for the parent and the heir inside the mixin.

• There is a tradeoff in the translation to java: code duplication vs. loosing encapsulation.