In the following example code:
#lang racket/base
(require
racket/class
racket/contract)
(define/contract parent%
(class/c (override [meth (->m string? void?)]))
(class object%
(super-new)
(abstract meth)))
(define/contract child-1%
(class/c [meth (->m string? void?)])
(class parent%
(super-new)
(define/override (meth str)
(displayln str))))
(define child-2%
(class parent%
(super-new)
(define/override (meth str)
(displayln str))))
(module+ test
(require rackunit)
(let ([child-1 (new child-1%)]
[child-2 (new child-2%)])
(check-exn exn:fail? (lambda() (send child-1 meth 1)))
(check-exn exn:fail? (lambda() (send child-2 meth 1)))
))
the first contract exception check succeeds (a contract exception is raised) but the second fails:
$ raco test contract-abstract-override.rkt
raco test: (submod "contract-abstract-override.rkt" test)
1
--------------------
FAILURE
name: check-exn
location: contract-abstract-override.rkt:31:4
params: '(#<procedure:exn:fail?> #<procedure:...stract-override.rkt:31:25>)
message: "child-2"
--------------------
1/2 test failures
I was kind of expecting the contract on meth
to be inherited in child-2%
. It is, after all, attached to the original, overridden method. Am I doing this wrong or is it always necessary to redefine contracts for overridden methods?
I also tried this without the abstract
part, using define/public
in parent%
. I got the same result.