Recently I'm learning Racket's trait system.
I did some experiments about super call in two mutually recursive methods:
I first experimented with mixin, it works as expected:
#lang racket
(define fish%
(class object% (super-new)
(define/public (get-color)
(println "fish% get-color"))
(define/public (get-price)
(println "fish% get-price"))
))
(define (spots-mixin %)
(class % (super-new)
(define/override (get-color)
(println "spots-mixin get-color")
(super get-price))
(define/override (get-price)
(println "spots-mixin get-price")
(super get-color)) ))
(define spots%
(spots-mixin fish%))
(send (new spots%) get-color)
(send (new spots%) get-price)
; Output:
; "spots-mixin get-color"
; "fish% get-price"
; "spots-mixin get-price"
; "fish% get-color"
Then I experimented with the trait, but failed:
#lang racket
(require racket/trait)
(define fish%
(class object% (super-new)
(define/public (get-color)
(println "fish% get-color"))
(define/public (get-price)
(println "fish% get-price"))
))
(define spots-trait
(trait
(define/override (get-color)
(println "spots-trait get-color")
(super get-price))
(define/override (get-price)
(println "spots-trait get-price")
(super get-color))
))
(define spots%
((trait->mixin spots-trait) fish%))
(send (new spots%) get-color)
(send (new spots%) get-price)
The REPL told me:
; class*: superclass does not provide an expected method for override
; override name: member68863
; class name: ...cts/racket/trait.rkt:367:17
I just define 2 methods in the super class fish% and 2 methods in the trait spots-trait to override them.
Why superclass does not provide an expected method for override ?
Is there a way to fix this error?
BTW, if I declare an additional (inherit/super get-color get-price) in the spots-trait, the REPL will complain:
get-color: duplicate definition of external name in trait
; in: get-color
Very thanks!
Update:
Recently I re-read the paper "Scheme with Classes, Mixins, and Traits", it mentioned that
Special care is required if a super call is allowed in a method other than an overriding implementation, and a cycle of mutually super-calling methods may require an indirection to prevent a super call from accessing an implementation in the trait instead of the base class. Fortunately, the trait-application operator can generate this indirection automatically.
This seems to be related to the question, but I don't quite understand what it mean. (e.g. what is "indirection").