[racket] Overriding methods in Racket classes

From: Harry Spier (vasishtha.spier at gmail.com)
Date: Thu Jan 3 23:42:57 EST 2013

OK using define-local-member-name works, see case 1 below, but it
seems it would be much simpler if there was a form define/inheritable
which made the method accessable within the class body where it was
defined and in the sub-class bodies only. (see case 2 below)
i.e. no wrapping in a let that returned multiple values etc.

Is there some reason there isn't such a form define/inheritable ?

===================================
Case 1 (using define-local-member-name)
=================================
#lang racket
(define-values (fish% picky-fish%)
  (let ()
    (define-local-member-name grow)
(define fish% (class object%
  (init size)                ; initialization argument

  (define current-size size) ; field

  (super-new)                ; superclass initialization

  (define/public (get-size)
    current-size)

  (define/public (grow amt)
    (set! current-size (+ amt current-size)))

  (define/public (eat other-fish)
    (grow (send other-fish get-size)))))

(define picky-fish% (class fish% (super-new)
                      (define/override (grow amt)

                        (super grow (* 3/4 amt)))))
    (values fish% picky-fish%)))

(define joe-the-minnow (new fish% [size 2]))
(define bud-the-minnow (new fish% [size 2]))
(define big-al-the-pike (new fish% [size 10]))
(define picky-selma (new picky-fish% [size 5]))

(send picky-selma eat joe-the-minnow)
(send picky-selma get-size)

;;this now correctly fails
;(send bud-the-minnow grow 5)
====================================
(Case 2 using a hypothetical define/inheritable)
====================================
#lang racket

(define fish% (class object%
  (init size)

  (define current-size size)

  (super-new)

  (define/public (get-size)
    current-size)

  (define/public (grow amt)
    (set! current-size (+ amt current-size)))

  (define/inheritable (eat other-fish) ;;;hypothetical define/inheritable
    (grow (send other-fish get-size)))))

(define picky-fish% (class fish% (super-new)
                      (define/override (grow amt)

                        (super grow (* 3/4 amt)))))

(define joe-the-minnow (new fish% [size 2]))
(define bud-the-minnow (new fish% [size 2]))
(define big-al-the-pike (new fish% [size 10]))
(define picky-selma (new picky-fish% [size 5]))

(send picky-selma eat joe-the-minnow)
(send picky-selma get-size)

Thanks,
Harry Spier







On 1/3/13, Asumu Takikawa <asumu at ccs.neu.edu> wrote:
> On 2013-01-03 17:01:54 -0500, Harry Spier wrote:
>> In Racket is it possible to override a non-public method?
>>
>> [...]
>>
>> Apologies if I've missed something obvious but I've just started going
>> through the Classes and Objects documentation.  I can see where you
>> can declare a method public and overridable, or public and not
>> overridable, but I don't see a declaration for a method to be private
>> to the outside world but public and overridable to its sub-classes.
>
> You can use local member names to accomplish this. It effectively makes
> certain method names lexically scoped. Here is an example:
>
>   #lang racket
>
>   (define-values (bomb% detonator%)
>     (let ()
>       ;; lexically scoped method name
>       (define-local-member-name detonate)
>       (values
>        (class object%
>          (super-new)
>          ;; public only while the name is in scope
>          (define/public (detonate)
>            (displayln "boom!")))
>        (class object%
>          (super-new)
>          (init-field bomb)
>          (define/public (trigger)
>            (send bomb detonate))))))
>
>   ;; error since `detonate` not in scope
>   ;(send (new bomb%) detonate)
>
>   ;; works
>   (send (new detonator% [bomb (new bomb%)]) trigger)
>
> Using local member names, the "outside world" is wherever the name is
> not bound. If it is in scope, you can invoke it, override it, etc and
> your method declarations are done normally.
>
> Cheers,
> Asumu
>

Posted on the users mailing list.