[plt-scheme] "appending" to classes rather than extending

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Thu Mar 6 22:22:03 EST 2008

On Mar 6, 2008, at 8:56 PM, Jakub Piotr Cłapa wrote:

> Matthias Felleisen wrote:
>> Let me rephrase my answer:
>> The purpose of a class is to protect some invariant relationship  
>> among the fields and methods. When you don't have the source code  
>> of a class, how can  you be sure that "class appending" doesn't  
>> violate the relationships -- the original intent (to use an  
>> American term) -- of the author(s)?
> I guess the answer is: You can't. That's why this is considered  
> fragile. On the other hand if it works well enough (i.e. was tested  
> in the intended application) than from an engineering point of view  
> it is OK. It's difficult prove that you program has no bugs. Either  
> with or without class modification.

I know this position very well of course. In the Lisp world it's all  
about loading and evaling and whatever. I just think that the real  
goal is a path between the two extremes: neither totally static  
(where you can basically prove things) nor totally dynamic (where you  
can't prove anything).

>> For many cases I suspect that class extension suffices.
> But it does not work well with object factories (and these may be  
> quite common) which return those types you need to augment and it  
> won't fix existing instances (e.g. singletons) .

No it won't -- and I don't think you want that. Imagine an extensible  
OS It accepts objects that satisfy certain properties and it  
occasionally calls some methods on them -- inside the kernel. Now  
imagine adding random code to the object's class, and bang! The OS  
should feel cheated when some method call suddenly diverges or whatever.

>> I guess this is more like replacing/adding methods in a vendor  
>> provided GUI Button class (or something similar) at the very  
>> beginning of your code than about upgrading code without  
>> interruption (as in Erlang).

No, if you set up things properly, you can replace some things and  
not others. Here is a strange beast:

(define stack%
  (class object%
    (define/public (push x) (push-internal x))
    (define (push-internal x) ...)
    (define/public (replace-push! f) (set! push-internal f))))

This stack class allows you to change the push method. It's  
anticipated. You could even set up a protocol for adding methods. If  
you so wish. And with macros you could make the entire class prepare  
itself for such changes. But I don't think you ever want that.

-- Matthias

Posted on the users mailing list.