<<

◦ ◦◦◦ TECHNISCHE UNIVERSITAT¨ MUNCHEN¨ ◦◦◦◦ ◦ ◦ ◦◦◦ ◦◦◦◦ ¨ ¨ ◦ ◦◦ FAKULTAT FUR INFORMATIK

Programming Languages

Mixins

Dr. Michael Petter Winter 2014

Mixins 1 / 30 “What advanced techiques are there besides multiple implementation inheritance?”

Mixins Introduction 2 / 30 Outline

Weak implementation inheritance

1 Decorator Problem 2 Wrapper Problem

Inheritance in Detail

1 Models for single inheritance 2 Introducing Mixins 3 Modelling Mixins

Mixins in the wild

1 Mixins as C++-Pattern 2 Native Mixins

Mixins Introduction 3 / 30 The Adventure Game

Door

ShortDoor LockedDoor canPass(Person p) canOpen(Person p) ? ShortLockedDoor canOpen(Person p) canPass(Person p)

Mixins Introduction The Adventure Game 4 / 30 The Adventure Game Door Doorlike canPass(Person p) canOpen(Person p) Short canPass(Person p)

Locked canOpen(Person p)

ShortLockedDoor ! Door implements empty methods canOpen(Person p) ! Doorlike must anticipate wrappers canPass(Person p)

Mixins Introduction The Adventure Game 5 / 30 The Wrapper

FileStream SocketStream read() read() write() write() ? SynchRW acquireLock() releaseLock()

! Cannot inherit from both seperately ! Creating new wrapping Classes duplicates code

Mixins Introduction The Wrapper 6 / 30 The Wrapper Stream read() write()

FileStream SocketStream read() read() write() write()

SynchRW read() ! Undoes specialization write() ! acquireLock() Needs common ancestor releaseLock()

Mixins Introduction The Wrapper 7 / 30 “Let’s go back to the basics of inheritance”

Mixins Mixins Modelling Inheritance 8 / 30 Classes and Methods The building blocks for classes are a countable set of method names N a countable set of method bodies B Classes map names to elements from the flat lattice B (called bindings), consisting of: method bodies ∈ B or classes ∈ C attribute offsets ∈ N+ ⊥ (yet) undefined > in conflict and the partial order ⊥ v m v > for each m ∈ B Definition (Abstract Class ∈ C) A partial function c : N 7→ B is called abstract class.

Definition ( and Class) An abstract class c is called (with pre beeing the preimage)

interface iff ∀n∈pre(c) . c(n) = ⊥. (concrete) class iff ∀n∈pre(c) . ⊥ @ c(n) @ >.

Mixins Mixins Modelling Inheritance 9 / 30 Computing with Classes and Methods

Definition (Family of classes C) We call the set of all maps from names to bindings the family of abstract classes C := N 7→ B.

Several possibilites for composing maps C  C: the symmetric join t, defined componentwise:

 b2 if b1 = ⊥ or n∈ / pre(c1)  b1 if b2 = ⊥ or n∈ / pre(c2) (c1 t c2)(n) = b1 t b2 = where bi = ci(n) b2 if b1 = b2  > otherwise

in contrast, the asymmetric join t, defined componentwise: ( c1(n) if n ∈ pre(c1) (c1 t c2)(n) = c2(n) otherwise

Mixins Mixins Modelling Inheritance 10 / 30 Example: -Inheritance

Smalltalk inheritance is the archetype for inheritance in mainstream languages like Java or C# inheriting smalltalk-style establishes a reference to the parent

Definition (Smalltalk inheritance (.)) Smalltalk inheritance is the binary operator . : C × C 7→ C, definied by c1 . c2 = {super 7→ c2} t (c1 t c2)

Example: Doors

Door = {canP ass 7→ ⊥, canOpen 7→ ⊥} LockedDoor = {canOpen 7→ 0x4204711} . Door

= {super 7→ Door} t ({canOpen 7→ 0x4204711} t Door) = {super 7→ Door, canOpen 7→ 0x4204711, canP ass 7→ ⊥}

Mixins Mixins Modelling Inheritance 11 / 30 Excursion: Beta-Inheritance In Beta-style inheritance the design goal is to provide security from replacement of a method by a different method. methods in parents dominate methods in subclass the keyword inner explicitely delegates control to the subclass

Definition (Beta inheritance (/)) Beta inheritance is the binary operator / : C × C 7→ C, definied by c1 / c2 = {inner 7→ c1} t (c2 t c1) Example (equivalent syntax): class Person{ String name= "Axel Simon"; public String toString(){ return name+inner.toString();}; }; class Graduate extends Person{ public extension String toString(){ return ", Ph..";}; };

Mixins Mixins Modelling Inheritance 12 / 30 Extension: Attributes

Remark: Modelling attributes is not in our main focus. Anyway, most mainstream languages nowadays are designed so that attributes are not overwritten: Definition (Mainstream inheritance (.0)) The extended mainstream inheritance .0 : C × C 7→ C binds attributes statically:  c2 if n = super  + 0 > if n ∈ pre(c1) ∧ c2(n) ∈ N (c1 . c2)(n) = c1(n) if n ∈ pre(c1)  c2(n) otherwise

Mixins Mixins Modelling Inheritance 13 / 30 “So what do we really want?”

Mixins Mixins Introducing Mixins 14 / 30 Adventure Game with Code Duplication

Door

ShortDoor LockedDoor canPass(Person p) canOpen(Person p)

ShortLockedDoor canOpen(Person p) canPass(Person p)

Mixins Mixins Introducing Mixins 15 / 30 Adventure Game with Mixins

Locked Door canOpen(Person p) canOpen(Person p) canPass(Person p)

Short mixin canPass(Person p)

compose ShortLocked

Mixins Mixins Introducing Mixins 16 / 30 Adventure Game with Mixins class Door{ boolean canOpen(Person p){ return true;}; boolean canPass(Person p){ returnp.size()< 210;}; } mixin Locked{ boolean canOpen(Person p){ if(!p.hasItem(key)) return false; else return super.canOpen(p); } } mixin Short{ boolean canPass(Person p){ if(p.height()>1) return false; else return super.canPass(p); } } class ShortDoor= Short(Door); class LockedDoor= Locked(Door); mixin ShortLocked= Short o Locked; class ShortLockedDoor= Short(Locked(Door)); class ShortLockedDoor2= ShortLocked(Door);

Mixins Mixins Introducing Mixins 17 / 30 Back to the blackboard!

Mixins Mixins Modelling Mixins 18 / 30 Abstract model for Mixins A Mixin is a unary second order type expression. In principle it is a curried version of the Smalltalk-style inheritance operator. In certain languages, programmers can create such mixin operators:

Definition (Mixin) The mixin constructor mixin : C 7→ (C 7→ C) is a unary class function, creating a unary class operator, defined by:

mixin(c) = λx . c . x

! Note: Mixins can also be composed ◦:

Example: Doors

Locked = {canOpen 7→ 0x1234} Short = {canP ass 7→ 0x4711} Composed = mixin(Short) ◦ (mixin(Locked)) = λx . Short . (Locked . x)

= λx . {super 7→ Locked} t ({canOpen 7→ 0x1234, canP ass 7→ 0x4711} . x)

Mixins Mixins Modelling Mixins 19 / 30 Wrapper with Mixins

FileStream SocketStream read() read() write() write()

mixin SynchRW acquireLock() releaseLock() mixin

SynchedFileStream SynchedSocketStream read() read() write() write()

Mixins Mixins Modelling Mixins 20 / 30 Mixins on Implementation Level

Short class Door{ boolean canOpen(Person p)... canPass() boolean canPass(Person p)... } super mixin Locked{ boolean canOpen(Person p)... Locked ... } canOpen() mixin Short{ boolean canPass(Person p)... super } class ShortDoor ... = Short(Door); Door class ShortLockedDoor = Short(Locked(Door)); ... ! non-static super-References ShortDoor d = new ShortLockedDoor(); dynamic dispatching without precomputed virtual table

Mixins Mixins Modelling Mixins 21 / 30 “Surely is powerful enough to simulate mixins?”

Mixins Mixins Simulating Mixins in C++ 22 / 30 Simulating Mixins in C++ template class SyncRW: public Super { public: virtual int read(){ acquireLock(); int result= Super::read(); releaseLock(); return result; }; virtual void write(int n){ acquireLock(); Super::write(n); releaseLock(); }; // ... acquireLock & releaseLock };

Mixins Mixins Simulating Mixins in C++ 23 / 30 Simulating Mixins in C++

template class LogOpenClose: public Super { public: virtual void open(){ Super::open(); log("opened"); }; virtual void close(){ Super::close(); log("closed"); }; protected: virtual void log(char*s) { ... }; }; class MyDocument: public SyncRW> {};

Mixins Mixins Simulating Mixins in C++ 24 / 30 True Mixins vs. C++ Mixins True Mixins super natively supported C++ Mixins Mixins as Template do not offer composite mixins Mixins reduced to templated superclasses C++ not modular Can be seen as coding Mixins have to stay source pattern code Hassle-free simplified version of multiple inheritance

Common properties of Mixins Linearization is necessary Exact sequence of Mixins is relevant

Mixins Mixins Simulating Mixins in C++ 25 / 30 “Ok, ok, show me a language with native mixins!”

Mixins Mixins Native Mixins in Python 26 / 30 Ruby module Short def canPass(p) class Person p.size< 160 and super(p) attr_accessor :size end def initialize end @size= 160 module Locked end def canOpen(p) def hasKey p.hasKey() and super(p) true end end end end class Door class ShortLockedDoor< Door def canOpen(p) include Short true include Locked end end def canPass(person) person.size< 210 p= Person.new end d= ShortLockedDoor.new end putsd.canPass(p)

Mixins Mixins Native Mixins in Python 27 / 30 Ruby class Door module ShortLocked def canOpen(p) include Short true include Locked end end def canPass(person) class Person person.size< 210 attr_accessor :size end def initialize end @size= 160 module Short end def canPass(p) def hasKey p.size< 160 and super(p) true end end end end module Locked def canOpen(p) p= Person.new p.hasKey() and super(p) d= Door.new end d.extend ShortLocked end putsd.canPass(p)

Mixins Mixins Native Mixins in Python 28 / 30 Lessons Learned

Lessons Learned

1 Formalisms to model inheritance 2 Mixins provide soft multiple inheritance 3 Multiple inheritance can not compensate the lack of super reference 4 Full extent of mixins only when mixins are 1st class language citizens

Mixins Mixins Native Mixins in Python 29 / 30 Further reading...

Gilad Bracha and William Cook. Mixin-based inheritance. European conference on object-oriented programming on Object-oriented programming systems, languages, and applications (OOPSLA/ECOOP), 1990.

James Britt. Ruby 2.1.5 core reference, December 2014. URL https://www.ruby-lang.org/en/documentation/.

Matthew Flatt, Shriram Krishnamurthi, and Matthias Felleisen. Classes and mixins. Principles of Programming Languages (POPL), 1998.

Mixins Further materials 30 / 30