I have in fact found an answer to the interface part of my question (see caveat below) in the docs right here: 4 Typed Classes , in the documentation for #:implements
. Here is how it applies to my original example:
(define-type my-interface<%> (Class (abstract-increment (-> Integer Integer))))
(: my-impl% (Class #:implements my-interface<%>
(extra-method (-> String))))
(define my-impl%
(class object%
(super-new)
(define/public (abstract-increment x) (+ x 1))
(define/public (extra-method) "I am an extra method")))
;(define obj1 (new my-interface<%>)) ; Type name used out of context.
(define obj2 (new my-impl%))
(send obj2 abstract-increment 1)
(send obj2 extra-method)
That's quite cool, because you get actual interfaces. You just need to keep in mind that you get them via a different mechanism than (untyped) Racket's interface
construct.
Caveat: This almost works for me, because ideally I would like to pass type parameters to the parent class/interface (cf. this other question), and #:implements
does not accept type constructors.