[plt-scheme] A puzzle for those people doing class.ss stuff
On Mon, 20 Nov 2006, Robby Findler wrote:
> Do you realize that you haven't defined any methods in the code below?
>
> It is a subtle point of the class system, but definitions that are
> otherwise unannotated (ie, don't have a /public or /private etc on them)
> are private fields.
Yes. I was just trying to distill the particular issue I was running into
in some other piece of code. The module I coded up just pinpoints the
problem to the call to super-new before the definition of 'x'.
I'm not really writing code like that in real life! (Unless I'm trying to
isolate something weird. *grin*)
The problem is that in the call to super-new in some-class:
(super-new)
sets 'x' to some certain value. But subsequently, the define:
(define x #f)
resets the value. That's the unexpected behavior. The fix is to pull
super-new to after the definition:
(define (my-mixin super%)
(class super%
(override set-x)
(define x #f)
(super-new)
...))
But this is subtle stuff. In particular, one reason reason this is odd is
because this conflicts with the standard Java way of implementing class
initializers --- in Java, the call to the super's initializer must come
first. Whereas in my code, if I do that, it screws things up.
For completeness's sake: in real life, I was defining a mixin for a
DrScheme unit window that define/override'ed the
FILE-MENU:BETWEEN-PRINT-AND-CLOSE function, and it looked something like
this:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (diva:menu-option-frame-mixin super%)
(class super%
(super-new)
(define enable/disable-menu-item #f)
(define/override (file-menu:between-print-and-close)
(super file-menu:between-print-and-close)
(set! enable/disable-menu-item
(new menu-item%
[label enable-divascheme-msg]
[parent menu]
[callback
(lambda (menu-item control-event)
(send (get-diva-central) switch-toggle))])))
(define (handle-diva-central-evt evt)
(match evt
[(struct diva-switch-on-evt ())
(when enable/disable-menu-item
(send enable/disable-menu-item set-label
disable-divascheme-msg))]
[(struct diva-switch-off-evt ())
(when enable/disable-menu-item
(send enable/disable-menu-item set-label
enable-divascheme-msg))]
[else
(void)]))
(send (get-diva-central) add-listener handle-diva-central-evt)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Some of the stuff there is just setting up the observer pattern. Anyway,
my handle-DIVA-CENTRAL-EVT told me that my menu item wasn't ever a true
value, and that was really confusing. I couldn't figure out why in the
world ENABLE/DISABLE-MENU-ITEM was getting lost after the call to
FILE-MENU:BETWEEN-PRINT-AND-CLOSE, because the menu-item was clearly being
instantiated.
So I cooked up that test-class-scoping code and played with it until I
could get it to exhibit the same variable-munging behavior. Anyway, I
hope that explains things.