Attempt to call `super` outside of overriding method in the trait which has two "mutually recursive" methods, but failed

Viewed 86

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").

0 Answers
Related