Presentation is loading. Please wait.

Presentation is loading. Please wait.

Designing a Java Extension with Mixins Presented by: Yoav Gur

Similar presentations


Presentation on theme: "Designing a Java Extension with Mixins Presented by: Yoav Gur"— Presentation transcript:

1 Designing a Java Extension with Mixins Presented by: Yoav Gur

2 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.

3 “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.

4 “…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”.

5 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); }

6 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 { }

7 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.

8 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.

9 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.

10 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 { }

11 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(); }

12 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.

13 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.

14 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.

15 Unexpected Overriding Mixin M, method m M, class C, method m C The names of m M and m C are identical. Signatures are identical However, M does not declare m C 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!

16 Illegal Overriding Mixin M, method m M, class C, method m C The names of m M and m C 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

17 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 chosen class C { void m(Integer i) {} void m(String s) {} } (new C()).m(null) No Solutio n

18 Java Ambiguity Resolution Tournament Characterizes a candidate –C: The declaring class –Pi: The i th parameter type vs. –Signs: C 1 ≥ C 2 ≡ “C 1 is equally or more specific then C 2 ” Pi 1 ≥ Pi 2 ≡ “P 1 is equally or more specific then P 2 ” – will win iff: C 1 ≥ C 2 AND P1 1 ≥ P1 2 AND … AND Pn 1 ≥ Pn 2 If there is more then one champion: –No Solution

19 Ambiguous Overloading with Mixins – Motivation (1) Mixin M, method m M, class C, method m C, mixin instance H –m M may be an inherited method An overloading relation between m M and m C 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 m M and m C

20 Ambiguous Overloading with Mixins - Motivation (2) m C is inheritedm C 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 m M and m C –Ambiguous call to m M () either from inside M (this.m M ()) or from outside M (H.m M ()) Without the third constraint:

21 Ambiguous Overloading with Mixins Solution - Third implicit constraint: –m C is not inherited –The names of m M and m C 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.

22 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 rules Solution: “this” has type M, but it cannot be passed as an argument! It can be assigned to other variables, of explicit type M.

23 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.

24 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.

25 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.

26 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.

27 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.


Download ppt "Designing a Java Extension with Mixins Presented by: Yoav Gur"

Similar presentations


Ads by Google