Download presentation
Presentation is loading. Please wait.
Published byLara Hoggarth Modified over 9 years ago
2
Flattening and Direct semantics By example: Inheritance Featherweight Jigsaw (FJig) (nice and clean) surface syntax Generalized inheritance I’ll gloss over its (ugly but equivalent) core syntax Conclusions
4
Please think how you’d explain inheritance to a muggle 1 ( 1 here, indicates someone who’s never heard of OO) Odds are you’re thinking of flattening semantics
5
class C1 { void m1() {…} } class C2 extends C1 { void m2() {…} } It’s as we wrote C2 like this class C2 { void m1() {…} void m2() {…} } What does this mean?
6
Extended Language Giving semantics of some feature by translating it away Programs translated in (equivalent) programs that don’t use the feature Language class C2 extends C1 { void m2() {…} } class C2 { void m1() {…} void m2() {…} } Extension flattened into the vanilla language Let’s see pros and cons
7
class C1 { void m1() {…} } class C2 extends C1 { void m2() {…} } class C3 extends C2 { void m3() {…} } class C1 { void m1() {…} } class C2 { void m1() {…} void m2() {…} } class C3 { void m1() {…} void m2() {…} void m3() {…} }
8
class C1 { void m1() {…} } class C2 { void m1() {…} void m2() {…} } class C3 { void m1() {…} void m2() {…} void m3() {…} } Lookup as easy as it can get No changes in the definition (the program changes, not lookup) For instance, lookup(C2, …)= (inheritance has been flattened out)
9
class C1 { void m1() {…} } class C2 extends C1 { void m2() {…} } class C3 extends C2 { void m3() {…} } class C1 { void m1() {…} } class C2 { void m1() {…} void m2() {…} } class C3 { void m1() {…} void m2() {…} void m3() {…} } the binary depends on
10
Intuitive: good tool for teaching/understanding Been used to give the semantics of mixins, traits, … but Poor implementation choice Lot of compiling dependencies (unlike Java, like C++) Code bloating
12
Please think how you’d implement inheritance Odds are you’re thinking of direct semantics
13
Extended Language class C2 extends C1 { void m2() {…} } Classes can be defined in new ways Since programs are not translated, good old method lookup can’t work anymore Language class C1 { void m1() {…} } We can compute lookup(C, m)=… For instance, lookup(C1, m1)=… lookup(C2, m1)=???
14
Needs to know what extends means For instance, lookup(C3, m2) starts from C3 Don’t find m2, so proceeds with C2 And finds m2 class C1 { void m1() {…} } class C2 extends C1 { void m2() {…} } class C3 extends C2 { void m3() {…} }
15
FlatteningDirect IntuitiveYESLess than the other Good old method lookup YESNO Is efficient?NOYES
17
class C ClassExpression ClassExpression ::= BasicClass | merge ClassExpression1, ClassExpression2 | rename N to N’ in ClassExpression | hide N in ClassExpression | …others… BasicClass ::= { …constr/fields/methods… }
18
One constructor; takes any kind of parameters Internal representation hidden from clients A series of members: fields and methods Members can be: abstract virtual frozen local no definition “someone” is expected to provide it there is a definition, but it can be later replaced there is a definition, that current clients will see forever (even if replaced) there is a definition, that no other object will ever see
19
Nice per se More than that, can encode: standard inheritance mixins traits … it’s a general framework for sw composition Wouldn’t be wonderful to have an intuitive (flattening) semantics and a (rather complex but) efficient (direct) one? Actually, no it wouldn’t … unless they’re equivalent! And they are!
20
class A { abstract void m(); frozen int answer() { return 41; } local int loc() { return 1; } } class B { frozen int answer() { return 42; } virtual void m() { loc(); } local int loc() { return answer(); } } class C merge (rename answer to wrongAnswer in A), B …what’s new C().answer()? I’m “cheating” using an extra-sugared syntax primitive types and void
21
class C merge (rename answer to wrongAnswer in A), B class C merge (rename answer to wrongAnswer in { abstract void m(); frozen int answer() { return 41; } local int loc() { return 1; } } ), B
22
class C merge { abstract void m(); frozen int wrongAnswer() { return 41; } local int loc() { return 1; } }, B
23
class C merge { abstract void m(); frozen int wrongAnswer() { return 41; } local int loc() { return 1; } }, { frozen int answer() { return 42; } virtual void m() { loc(); } local int loc() { return answer(); } }
24
class C merge { abstract void m(); frozen int wrongAnswer() { return 41; } local int loc() { return 1; } }, { frozen int answer() { return 42; } virtual void m() { loc’(); } local int loc’() { return answer(); } }
25
class C { // equivalent flattened definition frozen int wrongAnswer() { return 41; } local int loc() { return 1; } frozen int answer() { return 42; } virtual void m() { loc’(); } local int loc’() { return answer(); } } now we can easily see what new C().answer() is and, quite obviously, it’s 42
26
class A { abstract void m(); frozen int answer() { return 41; } local int loc() { return 1; } } class C merge (rename answer to wrongAnswer in A), B again, what does new C().answer() means? what is lookup(C, answer)? class B { frozen int answer() { return 42; } virtual void m() { loc(); } local int loc() { return answer(); } }
27
class A { abstract void m(); frozen int answer() { return 41; } local int loc() { return 1; } } class C merge (rename answer to wrongAnswer in A), B class B { frozen int answer() { return 42;} virtual void m() { loc(); } local int loc() { return answer(); } } lookup(C, answer) = lookup(merge …, answer) = = lookup((rename…), answer) and non-deterministically = lookup(B, answer)
28
lookup(rename FromN to ToN in ClassExpression, N)= failure if N=FromN lookup(ClassExpression, FromN) if N=ToN lookup(ClassExpression, N) otherwise In the example: lookup((rename answer to wrongAnswer in A), answer) fails, so lookup(C, answer) = … 2 choices … = lookup(B, answer)
29
lookup(B, answer) = lookup( ClassExpression, answer) where ClassExpression is the class expression of B, which is a base (flatten) class. So, we can conclude. Believe it or not, I’ve just scratched the surface: direct semantics is no picnic
30
Flatten semantics: easy, intuitive but “performs” poorly Direct semantics can be (rather) complex but it’s a good choice for implementation FJig: general language for software composition encompasses inheritance, mixin, traits…. Given both semantics and proved equivalent Implemented interpreter as master-thesis: http://www.disi.unige.it/person/LagorioG/FJig/ Exploring the equivalence for feature requiring static types (e.g. overloading and static binding) Investigating smart implementation techniques
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.