From: Matthew Flatt <mflatt@cs.utah.edu> To: plt-scheme@po.cs.brown.edu Subject: [plt-scheme] 299.10 Date: Wed, 23 Jun 2004 16:03:56 -0700 The v299-tagged code in CVS for MzScheme and MrEd is now version 299.10. (The exp-tagged code is still version 207.1.) Following tradition for a major version increment of PLT Scheme, we’re changing the class system --- not as much as in past versions, but enough to affect most code that uses "class.ss". The changes are in two parts: a syntactic clean-up for super calls, and new constructs for augment-only methods. The first part affects most code; the second affects code that uses certain MrEd methods (which must now be "augmented" instead of "overridden"). Augment-only methods are the subject of David Goldberg’s OOPSLA’04 paper, "Super and Inner --- Together at Last!" (to appear). I’ll ask David to post here when the paper becomes available. The short version is that we’re making Beta-style method augmentation and Java-style method overriding work together. Actually there’s one more change to "class.ss": keywords such as `public’ are now bound to syntactic forms that report out-of-context uses (much like `unquote’ and `unquote-splicing’). This minor change can break old code, but I expect that will be rare. More details are below, and temporary docs are in the usual place: http://www.cs.utah.edu/~mflatt/tmp/mzscheme-doc.plt http://www.cs.utah.edu/~mflatt/tmp/mzlib-doc.plt http://www.cs.utah.edu/~mflatt/tmp/mred-doc.plt Matthew ---------------------------------------- Super Calls ----------- A `rename’ clause is no longer necessary in a typical class with method overrides, due to the new `super’ form. For example, (class splotch% (rename [super-paint paint]) (define/override (paint x) (super-paint x) ....) (super-new)) can now be written (class splotch% (define/override (paint x) (super paint x) ....) (super-new)) An `override’ declaration enables the corresponding (internal) method name to be used with the `super’ form. The `super’ form is legal only for expressions within a `class’ (or `class*’, etc.). For cases where `super’ cannot be used --- either because no overriding method is declared in a class that calls a super method, or because the super call is in a lexically nested class --- the `rename-super’ form can be used just like the old `rename’ form. The script plt/notes/mzscheme/rename-super-fixup.ss may be useful for converting code that uses `rename’ to use `super’. (It’s a quick hack. Let me know if you create a better script.) Augment-Only Methods -------------------- A `pubment’ clause declares a method like `public’, but the resulting method cannot be overridden. Instead, the `pubment’ method can use `inner’ to dispatch to an augmenting method declared in a subclass. The word "pubment" is a contraction of "public, but merely augmentable in subclasses". The `inner’ expression form includes an expression to evaluate when a subclass does not provide an augmenting method. A subclass augments a `pubment’ method with `augment’ instead of `override’. The `augment’ declaration itself is non-overridable, and it can use `inner’ to allow further augmentation in further subclasses. Example: (define img% (class object% ;; No subclass can avoid clearing the dc in `paint’, ;; but a subclass can augment `paint’ to draw afterward. ;; The result indicates the size of the drawn image, ;; which is 0 if the paint method is not augmented. (define/pubment (paint dc) (send dc clear) (inner 0 paint dc)) (super-new))) (define box% (class img% ;; Add a square to the drawing, but allow subclasses ;; to draw first. Subclasses cannot skip the final ;; square-drawing step. Note that the result of the ;; method is the result of the `inner’ call, which is 20 ;; if the paint method is not augmented. (define/augment (paint dc) (begin0 (inner 20 paint dc) (send dc draw-rectangle 0 0 20 20))) (super-new))) (define frbox% (class img% ;; Add a larger red square as a background. (define/augment (paint dc) (send dc set-color (make-object color% "red")) (send dc draw-rectangle -1 -1 22 22) (send dc set-color (make-object color% "black")) (inner 22 paint dc)) (super-new))) (send (new img%) paint dc) ; => 0 ; and clears the dc (send (new box%) paint dc) ; => 20 ; and clears the dc, ; then draws a black rectangle (send (new frbox%) paint dc) ; => 22 ; and clears the dc, ; then draws a big red rectangle ; then draws a black rectangle An augmentation itself can be made overrideable using `augride’, which is a contraction of "augment, but allow the augment to be overridden". Similarly, `overment’ overrides a method, but allows subclasses only to augment this overridding. (define dot% (class img% ;; This augmentation of img% can be replaced in ;; subclasses. (define/augride (paint dc) (send dc draw-ellipse 0 0 20 20) 20) (super-new))) (define emptydot% (class dot% ;; Draw nothing, but still claim to have ;; drawn something of size 20. The dc is still ;; cleared in `paint’ from img%; the override ;; replaces only `paint’ in dot%. (define/override (paint dc) 20) (super-new))) (define frdot% (class dot% ;; This method re-uses the `paint’ augmentation in ;; dot%, and allows further augmentation in subclasses ;; (which cannot skip the painting here). (define/overment (paint dc) (send dc set-color (make-object color% "red")) (send dc draw-ellipse -1 -1 22 22) (send dc set-color (make-object color% "black")) (super paint dc) (inner 22 paint dc)) (super-new))) Note that `pubment’, `augment’, or `overment’ without an `inner’ call is effectively the same as `public-final’, `augment-final’, or `override-final’. However, the `-final’ variants report a class error if a subclass attempts to augment the method, whereas the non-`-final’ variants allow subclasses to include ans augmentation (that is always ignored). In general: Can use `inner’? Can use `super’? public N N pubment Y N override N Y augment Y N overment Y Y augride N N public-final N N override-final N Y augment-final N N The `rename-inner’ form is similar to `rename-super’. Like `rename-super’, it is rarely useful compared to `inner’. A use of a binding introduced by `rename-inner’ must include a `lambda’ pattern after the identifier to provide the default expression (i.e., the expression to evaluate if no subclass augments the method); see the documentation for further information. Keywords -------- The various keywords for class clauses are now all defined as syntax and exported by `(lib "class.ss")’. Use of a keyword in an expression positions produces a syntax error. A complete list of such keywords: private public override augment pubment overment augride public-final override-final augment-final field init init-field rename-super rename-inner inherit super inner MrEd Methods ------------ Some methods in MrEd are not augment-only. They no longer work with `override’ --- use `augment’, instead. top-level-window<%>: can-close? on-close editor<%>: on-change on-snip-modified can-save-file? on-save-file after-save-file can-load-file? on-load-file after-load-file on-edit-sequence after-edit-sequence text%: can-insert? on-insert after-insert can-delete? on-delete after-delete can-change-style? on-change-style after-change-style after-set-position can-set-size-constraint? on-set-size-constraint after-set-size-constraint pasteboard%: can-insert? on-insert after-insert can-delete? on-delete after-delete can-move-to? on-move-to after-move-to can-resize? on-resize after-resize can-reorder? on-reorder after-reorder can-select? on-select after-select can-interactive-move? on-interactive-move after-interactive-move can-interactive-resize? on-interactive-resize after-interactive-resize