[racket] How to use abstract classes?

From: Jon Rafkind (rafkind at cs.utah.edu)
Date: Wed Aug 24 16:20:08 EDT 2011

Here is the code. I had to split the abstract methods from the concrete methods in the interface. The trick with mixins is that they can't be instantiated
themselves, you have to apply them to some class and then instantiate that class.

#lang racket

(provide
  first-child-class%
  second-child-class%)

(define child-interface-partial
  (interface ()
             child-method
             ))

(define child-interface
  (interface (child-interface-partial)
             child-implementation-dependent-method))

#;
(define generic-parent-class%
  (class* object% ()
          (super-new)
          (define/public (child-method this-time) (error 'child-method "abstract method"))
          (define/public (child-implementation-dependent-method given-inputs-list)
            (map
              (lambda(this-item)
                (eprintf "Next list item is ~v" (child-method this-item)))
              given-inputs-list))))

(define generic-parent-class-mixin
  (mixin (child-interface-partial)
         (child-interface)

         (define/public (child-implementation-dependent-method given-inputs-list)
            (map
              (lambda(this-item)
                (eprintf "Next list item is ~v\n" (send this child-method this-item)))
              given-inputs-list))

         (super-new)))

(define first-child-class%
  (generic-parent-class-mixin
      (class* object% (child-interface-partial)
              (super-new)
              (define/public (child-method given-input)
                (string-append "First got  " given-input)))))

(define second-child-class%
  (generic-parent-class-mixin
    (class* object% (child-interface-partial)
            (super-new)
            (define/public (child-method given-input)
              (string-append "Second got  " given-input)))))

(define x1 (new first-child-class%))
(define x2 (new second-child-class%))

(send x1 child-implementation-dependent-method '("a" "b" "c"))
(send x2 child-implementation-dependent-method '("a" "b" "c"))

Output:
Next list item is "First got  a"
Next list item is "First got  b"
Next list item is "First got  c"
'(#<void> #<void> #<void>)
Next list item is "Second got  a"
Next list item is "Second got  b"
Next list item is "Second got  c"
'(#<void> #<void> #<void>)


On 08/24/2011 11:18 AM, Alexander Kasiukov wrote:
> Dear Jon,
>
> Thank you very much for your help! I got what I needed to work with method overrides (following a suggestion of Robby Findler), but it does look like mixins
> may give a less redundant way to accomplish the same functionality. I am at a loss trying to understand how to make them work based on the Bakus-Naur
> description. (I am just starting to learn Racket and Lisp in general.) Could you show an example or suggest a place where I can look up one? I am trying to do
> something along the lines of
>
> #lang racket
>
> (provide
>     first-child-class%
>     second-child-class%)
>
> (define child-interface
>     (interface ()
>         child-implementation-dependent-method
>         child-method))
>
> (define generic-parent-class%
>     (class* object% ()
>         (super-new)
>         (define/public (child-method this-time) (error 'child-method "abstract method"))
>         (define/public (child-implementation-dependent-method given-inputs-list)
>             (map
>                 (lambda(this-item)
>                     (eprintf "Next list item is ~v" (child-method this-item)))
>                 given-inputs-list))))
>
> (define first-child-class%
>     (class* generic-parent-class% (child-interface)
>         (super-new)
>         (define/override (child-method given-input)
>             (string-append "First got  " given-input))))
>
> (define second-child-class%
>     (class* generic-parent-class% (child-interface)
>         (super-new)
>     (define/override (child-method given-input)
>         (string-append "Second got  " given-input))))
>
> Sincerely yours,
> Alex
>> Date: Wed, 24 Aug 2011 09:04:40 -0600
>> From: Jon Rafkind <rafkind at cs.utah.edu>
>> To: users at racket-lang.org
>> Subject: Re: [racket] How to use abstract classes?
>> Message-ID: <4E551308.5020503 at cs.utah.edu>
>> Content-Type: text/plain; charset=ISO-8859-1
>>
>> You could use a mixin. http://docs.racket-lang.org/reference/mixins.html?q=mixin&q=class#(form._((lib._racket/private/class-internal..rkt)._mixin))
>>
>> On 08/24/2011 08:31 AM, Alexander Kasiukov wrote:
>>> Dear Racket users,
>>>
>>> What is the best way to make a class in Racket abstract? I would like to have a class which
>>>
>>>     never gets instantiated
>>>     implements certain methods common to all of its children
>>>     needs to call some of the methods implemented in the children.
>>>
>>> Sincerely yours,
>>> Alex
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20110824/87a66264/attachment.html>

Posted on the users mailing list.