I have read the Racket guide 13.7.3 Parameterized Mixins
I use Parameterized Mixins to create a class good-eat-fish%
from fish%
(define fish-interface
(interface () eat get-size))
(define fish%
(class* object% (fish-interface)
(init size)
(super-new)
(define current-size size)
(define/public (get-size) current-size)
(define/public (eat other)
(set! current-size (+ current-size (send other get-size))))))
(define (good-eat-mixin member-name)
(define eat member-name)
(mixin () ()
(inherit eat)
(define/public (good-eat y)
(eat y) (eat y))))
(define good-eat-fish%
((good-eat-mixin (member-name-key eat)) fish%))
When I run the code the following error is raised:
"mixin: method was referenced in definition, but is not in any of the from-interfaces
method name: eat
from-interfaces:"
Does this error message indicate that there's no eat
method?
If I change the code to
(define (good-eat-mixin member-name)
(define eat member-name)
(mixin (interface () eat) (interface () eat good-eat)
(inherit eat)
(define/public (good-eat y)
(eat y) (eat y))))
I get this error:
interface: bad syntax in: interface
Unfortunately, I don't know why
interface () eat)
is bad syntax.
For the first problem: mixins enforce a few checks for misuse, and you're running across them. For example, if you just do:
(mixin () ()
(inherit eat)
(define/public (good-eat y)
(eat y) (eat y)))
then the system detects that the code is trying to depend on an eat
method that isn't a part of the mixin's declared interface. Your second attempt is closer, but you need extra parens. e.g., from
(mixin (interface () eat) (interface () eat good-eat)
(inherit eat)
(define/public (good-eat y)
(eat y) (eat y)))
to:
(mixin ((interface () eat)) ((interface () eat good-eat))
(inherit eat)
(define/public (good-eat y)
(eat y) (eat y)))
Give names to the interfaces so that this is easier to see:
(define eater<%> (interface () eat))
(define good-eater<%> (interface () good-eat))
...
(mixin (eater<%>) (good-eater<%>)
...)
Here's an example:
#lang racket
(define eater<%> (interface () eat))
(define good-eater<%> (interface () good-eat))
(define fish%
(class* object% (eater<%>)
(init size)
(super-new)
(define current-size size)
(define/public (get-size) current-size)
(define/public (eat other)
(set! current-size (+ current-size (send other get-size))))))
(define fish-interface
(interface () eat get-size))
(define good-eat-mixin
(mixin (eater<%>) (good-eater<%>)
(inherit eat)
(super-new)
(define/public (good-eat y)
(eat y) (eat y))))
(define good-eat-fish%
(good-eat-mixin fish%))
(define f1 (new good-eat-fish% [size 42]))
(define f2 (new good-eat-fish% [size 16]))
(send f1 eat f2)
(send f1 good-eat f2)
(send f1 get-size)
(I stripped out the member key stuff out of your example, just to simplify.)
I believe the class system in racket/class
is nominal rather than structural.