# Typed abstract methods / typed interfaces

**URL:** <https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197>\
**Category:** Questions & Answers\
**Tags:** typed-racket\
**Created:** [August 1, 2022, 9:10pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197 "2022-08-01T21:10:27Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![scolobb](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/scolobb/32/108_2.png) [@scolobb](https://racket.discourse.group/u/scolobb)\
**Post date:** [August 1, 2022, 9:10pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197/1 "2022-08-01T21:10:27Z")

</div>

Hello,

I would like to define typed classes with abstract methods / interfaces. This is the approach I am going for at the moment:

```scheme

(define my-interface%
  (class object%
    (super-new)
    (: abstract-increment (-> Integer Integer))
    (define/public (abstract-increment x) (error 'abstract-increment "undefined"))))

(define my-impl%
  (class my-interface%
    (super-new)
    (define/override (abstract-increment x) (+ x 1))))

(define obj1 (new my-interface%))
;(send obj1 abstract-increment 1) ; => error "undefined"
(define obj2 (new my-impl%))
(send obj2 abstract-increment 1) ; => 2

```

Are there any better ways to achieve this?

I quickly looked at the implementation of [interface](https://docs.racket-lang.org/reference/createinterface.html#(form._((lib._racket%2Fprivate%2Fclass-internal..rkt)._interface))), and it seems quite unsurprisingly to be doing something more complex than what my code does.

---

<div class="post-metadata">

**Author:** ![capfredf](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/capfredf/32/935_2.png) [@capfredf](https://racket.discourse.group/u/capfredf)\
**Post date:** [August 2, 2022, 3:14pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197/2 "2022-08-02T15:14:28Z")

</div>

The object system in Racket is structural not nominal, so, if I understand you correctly, row polymorphism for typed code would be an ideal way to handle situations similar to yours. However, I recently found out that TR's local type inference currently does not support row polymorphism for objects.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [August 2, 2022, 4:28pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197/3 "2022-08-02T16:28:38Z")

</div>

It appears that typed/racket/class does not support the `abstract` form supported by racket/class. Perhaps this is a bug? Or perhaps `abstract` is hard for the semantics?

---

<div class="post-metadata">

**Author:** ![capfredf](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/capfredf/32/935_2.png) [@capfredf](https://racket.discourse.group/u/capfredf)\
**Post date:** [August 2, 2022, 6:48pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197/4 "2022-08-02T18:48:28Z")

</div>

Typed Racket's support for class/objects are experimental currently. I think it is not too hard to statically check if a class to be instantiated contains `abstract` methods (and/or ones inherited from its base classes)

[I can't speak for Asumu, but I think it was just because `abstract` added few interesting values from a gradual typing's perspective.]

I think I wasn't clear: for @scolobb's case, if interfaces (in an oo sense) are the only thing needed, then Typed Racket already has types to express them, but the corresponding support in the local type inference are not there yet.

---

<div class="post-metadata">

**Author:** ![scolobb](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/scolobb/32/108_2.png) [@scolobb](https://racket.discourse.group/u/scolobb)\
**Post date:** [August 2, 2022, 9:43pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197/5 "2022-08-02T21:43:03Z")

</div>

Thank you for your answers!

I think I get the gist of what you are saying @capfredf , which means that I will go with my crude approach for now. I have been poring on row polymorphism for some time now, and while the [basic definition](https://en.wikipedia.org/wiki/Row_polymorphism) seems rather clear, I am still not quite sure about the implications. More poring needed, and your answers are quite helpul 🙂

---

<div class="post-metadata">

**Author:** ![scolobb](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/scolobb/32/108_2.png) [@scolobb](https://racket.discourse.group/u/scolobb)\
**Post date:** [August 11, 2022, 1:46pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197/6 "2022-08-11T13:46:50Z")

</div>

I have in fact found an answer to the interface part of my question (see caveat below) in the docs right here: [4&nbsp;Typed Classes](https://docs.racket-lang.org/ts-reference/Typed_Classes.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fbase-types-extra..rkt%29._.Class%29%29) , in the documentation for `#:implements`. Here is how it applies to my original example:

```scheme
(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](https://racket.discourse.group/t/inheritance-of-parameterized-typed-classes/1217)), and `#:implements` does not accept type constructors.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [August 11, 2022, 2:39pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197/7 "2022-08-11T14:39:16Z")

</div>

Since `#:implements` doesn't accept constructors, could you write the equivalent of

```scheme
(define instantiated-type (my-interface-constructor<%> Integer))
(: my-impl% (Class #:implements instantiated-type …))

```

?

Not elegant, but might get the job done?

---

<div class="post-metadata">

**Author:** ![scolobb](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/scolobb/32/108_2.png) [@scolobb](https://racket.discourse.group/u/scolobb)\
**Post date:** [August 11, 2022, 4:42pm UTC](https://racket.discourse.group/t/typed-abstract-methods-typed-interfaces/1197/8 "2022-08-11T16:42:56Z")

</div>

Aah, that's clever, thank you! I am leaving on vacation right now, but I'll test it once I'm back in front of a computer.

I am not sure it solves my main problem, as I would essentially like to parameterize `instantiated-type` by a type variable coming from the signature of `my-impl%`, but I have to try!
