From kragen@dnaco.net Fri Jul 31 11:03:20 1998 Date: Fri, 31 Jul 1998 11:03:19 -0400 (EDT) From: Kragen To: "Bradley M. Kuhn" cc: clug-user@clug.org Subject: Re: OO in non OOP languages (was Re: OO in C (was Re: KDE crap)) In-Reply-To: <19980731101902.60030@ebb.org> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Keywords: X-UID: 916 Status: O X-Status: On Fri, 31 Jul 1998, Bradley M. Kuhn wrote: > Thus spoke James Weirich: > > drawn_object * rect = MakeRectangle (); > > rect->ftbl->Draw(rect); > > ((RectangleFuncTable*)rect->ftbl)->SetWidth (rect, 10); > > > > I suppose you could wrap the function table fetching in a function or > > macro that hides the casting ... > > > > AsShape(rect)->Draw(rect); > > AsRectangle(rect)->Draw(rect); /* I guess this would work too */ > > AsRectangle(rect)->SetWidth (rect, 10); > > > But that still is extra baggage to worry about. > > Hmmm...that's true. Perl [0] handles this better by using anonymous > subroutines with run-time binding. But that, of course, makes things slow. > :) I think Perl does its run-time binding by looking up the name of the message in a hash table, although I haven't actually read the code. If you wanted Perlian flexibility, you could get it more cheaply by interning all the message names into an obarray. void* invoke_method(void *object, int methodnum, ...) { va_list method_args; Obj* objobj = (Obj*) object; method* m; void *rv; va_start(method_args, method); if (!(m = lookup_method(objobj, methodnum)) { signal_smalltalklike_failure(objobj, methodnum); assert(0); /* previous line shouldn't return */ } else { rv = (*m)(objobj, methodnum, method_args); va_end(method_args); return rv; } } This would be somewhat clumsy to use, though. > > For "BIG" things that REALLY NEED polymorphism, I would agree the > > technique is worthwhile in C. But as general programming style for most > > of you data structures, I think the baggage quickly becomes unmanageable. > > Perhaps, but polymorphism is, and always will be, much slower. Usually slower. With the examples Jim and I posted previously, which are the usual C++ mechanism, "much slower" is a bit of an exaggeration -- the only cost is an additional fetch and add before the call. (Andras Zsoter's DOOF demonstrated that it was actually possible to squeeze that additional fetch into an x86 instruction such that polymorphic calls consumed no more instructions than non-polymorphic calls. He claimed that meant there was "no overhead", a claim I doubt.) Alan Kay pointed out that, before machines came equipped with MMUs, you could claim that "virtual memory is, and always will be, much slower". In fact, the original Mac implemented a sort of virtual memory in software, and it made it slower, and the same is true of Forth. > Regardless > if it "doesn't matter" because you have horsepower, you can still use that > horsepower more efficiently without polymorphism. Thus, as I said, base > libraries, IMHO, should be written as OO as possible as C can do (when OO is > appropriate, of course---it isn't always), and then wrapped with other OO > languages if needed. I disagree. sfio, which does everything stdio does and more, and uses run-time polymorphic method dispatch for all the methods, is usually faster than stdio. (sfio *is* written in C, though.) Part of the reason that sfio is faster is that it is better-designed, and part of that is due to polymorphic method dispatch. > [0] I mention Perl many times, because Perl is a language that was not > specifically designed for OO, but can handle OO very elegantly (more > elegantly than C, actually). Definitely. Very little was added to Perl to support its OOness. Kragen