[plt-scheme] "appending" to classes rather than extending
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%
(super-new)
(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