Hi all,
Recently I read the paper "Classes and Mixins" by Matthew Flatt, Shriram
Krishnamurthi and Matthias Felleisen.
In this paper, the authors presented MIXEDJAVA.
In MIXEDJAVA,
> A programmer implements mixins in exactly the same
> way as a derived class, except that the programmer cannot
> rely on the implementation of the mixin's superclass, only
> on its interface. We consider this an advantage of mixins
> because it enforces the maxim "program to an interface, not
> an implementation".
>
It is very close to the mixin form in Racket, because we can specific
interface in the mixin form:
```
(mixin (interface-expr ...) (interface-expr ...)
class-clause ...)
```
In Chapter 3, they also introduced an example (a maze adventure game, I
called it LockedMagicDoor) which uses the system.
My question is:
Is it possible to implement LockedMagicDoor in Racket?
I did some experiments but failed.
See following code (or
https://gist.github.com/chansey97/aecffabb2885c83fa040ba677bde5de4):
```
#lang racket
(define the-key 'the-key)
(define the-spell-book 'the-spell-book)
(define person%
(class object%
(init-field items h)
(super-new)
(define/public (has-item item)
(member item items))
(define/public (height)
h)
))
(define door<%> (interface () can-open can-pass))
(define door-mixin
(mixin () (door<%>)
(super-new)
(define/public (can-open p)
(println "door% can-open")
#t)
(define/public (can-pass p)
(println "door% can-pass")
#t)
))
(define secure-door<%> (interface (door<%>) needed-item))
(define secure-mixin
(mixin (door<%>) (secure-door<%>)
(super-new)
(define/public (needed-item) ;; error??
(println "secure-mixin needed-item")
#f)
(define/override (can-open p)
(println "secure-mixin can-open")
(define item (needed-item))
(cond
((not (send p has-item item)) (printf "You don't have the Key ~v\n"
item)
#f)
(else (printf "Using Key... ~v\n" item)
(super can-open p
))
(define locked-needed-mixin
(mixin (secure-door<%>) (secure-door<%>)
(super-new)
(define/override (needed-item)
(println "locked-needed-mixin neededItem")
the-key)
))
(define magic-needed-mixin
(mixin (secure-door<%>) (secure-door<%>)
(super-new)
(define/override (needed-item)
(println "magic-needed-mixin neededItem")
the-spell-book)
))
(define door%
(door-mixin object%))
(define locked-mixin (compose locked-needed-mixin secure-mixin))
(define magic-mixin (compose magic-needed-mixin secure-mixin))
(define locked-magic-mixin (compose locked-mixin magic-mixin))
(define locked-magic-door% (locked-magic-mixin door%))
(define door (new locked-magic-door%))
(send door can-open (new person% [items (list the-key the-spell-book)] [h
0.5]))
; class*: superclass already contains method
; superclass: #
; method name: needed-item
; class name: ...agic-door-failed.rkt:36:2
```
The problem is how to implement `secure-mixin`?
Notice that since the `secure-mixin` is mixed into `locked-magic-door%`
twice, there will be two `needed-item` methods in the inheritance chain, so
they are naming conflict.
However in MIXEDJAVA, they do not conflict:
> Specifically, a composition m1 compose m2 contains two methods named
> x if both m1 and m2 declare x and m1's inheritance interface does not
> contain x. Both x methods are accessible in an instance of the composite
> mixin since the object can be viewed specifically as an instance of m1 or
> m2.
>
Can someone help me? (e.g. make some changes to this code above and let it
work in Racket)
Very thanks.
I also attempt to use Inner to simulate the behavior of MIXEDJAVA:
```
(define secure-mixin
(mixin (door<%>) (secure-door<%>)
(super-new)
(define/pubment (needed-item)
(println "secure-mixin needed-item")
#f)
(define/override (can-open p)
(println "secure-mixin can-open")
(define item (inner #f needed-item))
(cond
((not (send p has-item item)) (printf "You don't have the Key ~v\n"
item)
#f)
(else (printf "Using Key... ~v\n" item)
(super can-open p
))
(define locked-needed-mixin
(mixin (secure-door<%>) (secure-door<%>)
(super-new)
(define/augride (needed-item)
(println "locked-needed-mixin neededItem")
the-key)
))
(define magic-needed-mixin
(mixin (secure-door<%>) (secure-door<%>)
(super-new)
(define/augride (needed-item)
(println "magic-needed-mixin neededItem")
the-spell-book)
))
```
But still failed:
; class*: superclass already contains method
; superclass: #
; method name: needed-item
See https://gist.github.com/chansey97/264d3435a8f506153709cc9804227fdf
PS: I also tried `overment` and `augment` for the `needed-item` in
`secure-mixin`, but failed as well