Next: methods sealing, Previous: methods concrete, Up: methods [Contents][Index]
The clause virtual-method
allows the definition of virtual
methods associated to a record–type. Virtual methods work almost like
concrete methods, but the rules of overriding are different: with
virtual methods we request run–time dynamic dispatching, to have the
methods of the sub–types take precedence over the methods of the
super–types.
NOTE Virtual methods must have an implementation, there are no abstract methods.
Example:
(define-record-type <super> (virtual-method (doit) 1)) (define-record-type <sub> (parent <super>) (method (doit) 2)) (define (super-fun {O <super>}) (.doit O)) (define (sub-fun {O <sub>}) (.doit O)) (define O (new <sub>)) (super-fun O) ⇒ 2 (sub-fun O) ⇒ 2
we see that even though the function super-fun
accesses the
instance of <sub>
with the type specification <super>
, the
actually called method is the one defined by <sub>
.
The overriding method’s type signature must be a sub–type of the overridden method’s type signature. For example, the following definitions are fine:
(define-record-type <super> (fields value) (virtual-method ({doit <number>} {S <nestring>}) (.value this))) (define-record-type <sub> (parent <super>) (virtual-method ({doit <fixnum>} {S <string>}) (.value this)))
because:
(type-annotation-super-and-sub? (lambda (<nestring>) => (<number>)) (lambda (<string>) => (<fixnum>))) ⇒ #t
while the following definitions will cause a syntax violation exception at expand–time:
(define-record-type <super> (fields value) (virtual-method ({doit <number>} {S <nestring>}) (.value this))) (define-record-type <sub> (parent <super>) (virtual-method ({doit <fixnum>} {S <vector>}) (.value this)))
because:
(type-annotation-super-and-sub? (lambda (<nestring>) => (<number>)) (lambda (<string>) => (<vector>))) ⇒ #f
Once a method has been defined as virtual in a super–type, it does not
matter if the sub–type makes use of method
,
virtual-method
or seal-method
: all these clauses will
override the super–type’s method if they use the same name. Example:
(define-record-type <super> (virtual-method (darkness) 1) (virtual-method (light) 2)) (define-record-type <sub> (parent <super>) (method (darkness) 11) (virtual-method (light) 22)) (define {P <super>} (new <sub>)) (.darkness P) ⇒ 11 (.light P) ⇒ 22
Notice that it is not possible to define a sub–type having a field with the same name of a super–type’s virtual method; the following definitions will cause an expand–time exception:
(define-record-type <super> (method (doit) 1)) (define-record-type <sub> (parent <super>) (fields doit)) error→ &syntax
The clause seal-method
seals a method name so that the
sub–types can no more use it; it does not matter if the super–types
actually use it or not.
Next: methods sealing, Previous: methods concrete, Up: methods [Contents][Index]