◦ ◦◦◦ 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
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 (Interface 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: Smalltalk-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.D.";}; };
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
compose
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
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 multiple inheritance is powerful enough to simulate mixins?”
Mixins Mixins Simulating Mixins in C++ 22 / 30 Simulating Mixins in C++ template
Mixins Mixins Simulating Mixins in C++ 23 / 30 Simulating Mixins in C++
template
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++ Type system 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