I agree that this doesn't look possible within a single class, but I
don't see any problem with the pattern (aside from being awkward to
write). As far as I can tell, it would make sense for `class` to
support new a case that fuses your `overment` plus `augride` steps.
Internally, that would create a new index for the method while wiring
`super` in subclasses directly to the superclass implementation.

Are there other useful variants that are not currently supported (at
least directly)? Why wasn't this one a blank space in the table of
possibilities that we sketched in the super+inner paper? I don't know.

At Sat, 17 Jul 2021 00:10:10 -0500, Alexis King wrote:
> Hello,
> 
> While doing some OOP in Racket today, I found myself in a situation that
> would benefit from two seemingly contradictory things:
> 
>    1.
> 
>    I want to be able to override a superclass method, and I want to be
>    certain that I get to handle the method before any of my subclasses do.
>    This suggests I want to use inner.
>    2.
> 
>    At the same time, I want my subclasses to be able to override this
>    method, not augment it. If I call inner and my subclass calls super,
>    control should jump to *my superclass*.
> 
> In other words, I want to get a sort of “first try” at handling the method
> so that if I choose to, I can neglect to call my subclass’s implementation
> altogether. But if I decide *not* to handle it, then I want super-style
> dispatch to proceed as if my class were never there at all.
> 
> At first, I thought this wasn’t possible using Racket’s class system, since
> if I override my superclass’s method using overment, the subclass
> necessarily cannot use super, violating requirement 2. Yet if I use override,
> I don’t get the “first try” I want, violating requirement 1. However, after
> some thought, I realized it’s possible if I’m willing to use *two* classes
> rather than one:
> 
> (define my-superclass%
>   (class object%
>     (define/public (m x) `(foo ,x))
>     (super-new)))
> 
> (define my-class%
>   (let ()
>     (define-local-member-name super-m)
>     (class (class my-superclass%
>              (define/public (super-m x)
>                (super m x))
>              (define/overment (m x)
>                (if (not x)
>                    'skip
>                    (inner (error "impossible") m x)))
>              (super-new))
>       (inherit super-m)
>       (define/augride (m x)
>         (super-m x))
>       (super-new))))
> 
> The trick here is twofold:
> 
>    1.
> 
>    First, I override m using overment, which ensures method dispatch will
>    call my implementation first.
>    2.
> 
>    Next, I augment my own implementation of m using augride, which makes
>    the method overridable again in subclasses. To satisfy the other half of
>    requirement 2, my augmentation calls my-superclass%’s implementation of m
>    via a sort of secret “side channel,” kept private using
>    define-local-member-name.
> 
> Using this trick, subclasses of my-class% can still override m, and as long
> as x is non-#f, my sneaky interposition doesn’t seem to have any effect.
> But if x *is* #f, I can short-circuit the computation immediately:
> 
> (define my-subclass%
>   (class my-class%
>     (define/override (m x)
>       `(baz ,(super m x)))
>     (super-new)))
> 
> (define obj (new my-subclass%))
> (send obj m #t) ; => '(baz (foo #t))
> (send obj m #f) ; => 'skip
> 
> I think this is kind of cute, since it makes it possible to effectively
> conditionally interpose on method dispatch. However, it’s rather awkward to
> write. This brings me to my question: is there any simpler way to do this?
> And are there any hidden gotchas to my technique?
> 
> Thanks,
> Alexis
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email 
> to [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/racket-users/CAA8dsae1HR2CVUNq3aC4nc2vpPU6L9f-
> ENor-074LyZnWXgKYg%40mail.gmail.com.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/20210719100827.35e%40sirmail.smtps.cs.utah.edu.

Reply via email to