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.

