[E-Lang] Re: inheritance, delegation, mental models for begin ners (was: down with `define' (was: newbie syntax: picayune points from a prejudiced programmer))

Karp, Alan alan_karp@hp.com
Fri, 2 Mar 2001 17:20:56 -0800


MarkM wrote:
>
> Btw, many of us, when doing class-based programming with inheritance,
mostly 
> stopped using concrete non-final classes since the Udanax Gold days.  When

> we found we wanted to subclass a concrete class, we refactored so that we 
> were subclassing from an abstract class.  I believe Dean was always the 
> biggest advocate of this design rule.  The E implementation grossly
violates 
> this, but that's only because of Java used to have a horrendous huge 
> per-class memory cost.  (It may still, but we should fix this anyway,
since 
> memory is now cheaper.)

I must have been doing something wrong, because I tried to do this (at least
I think I did), and I didn't like the result.  Say I have a class C with 2
methods, M1 and M2.  One subclass C1 overrides M1, another C2 overrides M2.
If C is a concrete class, then C1 gets C's M2, and C2 gets C's M1.  If C is
abstract in that it has no implementation for M1 and M2, where do these
implementations go?  I ended up with an extra abstract class between C and
each of C1 and C2.  Of course, it's not terrible with only 2 methods; my
case had 5.

_________________________
Alan Karp
Principal Scientist
Decision Technology Department
Hewlett-Packard Laboratories MS 1U-2
1501 Page Mill Road
Palo Alto, CA 94304
(650) 857-3967, fax (650) 857-6278
https://ecardfile.com/id/Alan_Karp
http://www.hpl.hp.com/personal/Alan_Karp/
 

> -----Original Message-----
> From: Mark S. Miller [mailto:markm@caplet.com]
> Sent: Friday, March 02, 2001 3:56 PM
> To: Marc Stiegler
> Cc: zooko@zooko.com; Tyler Close; Ka-Ping Yee; e-lang@eros-os.org;
> dworkin@dworkin.nl
> Subject: Re: [E-Lang] Re: inheritance, delegation, mental models for
> beginners (was: down with `define' (was: newbie syntax: 
> picayune points
> from a prejudiced programmer))
> 
> 
> At 11:01 AM Friday 3/2/01, Marc Stiegler wrote:
> >[With inheritance] if the subclass overrides a
> >method in the superclass, when the superclass calls that 
> method it goes back
> >out to the subclass's method. With delegation, a 
> delegated-to class call to
> >the overridden method is directed to the delegated-to class 
> implementation.
> 
> As Dean's message reveals, I may be badly out of touch with 
> how the world 
> uses terms these days.  However, my use of these terms agrees 
> with MarcS's, 
> which I believe agrees with the website and the list.  
> Therefore, when you say 
> 
> > The MUD programming languages [...] use the word
> > "inheritance" to mean the thing that we call "delegation".
> 
> followed by
> 
> > Since E is dynamically typed there is no really important 
> difference, is 
> > there? [2]
> 
> since the second doesn't correspond to our usage, I remain 
> curious about 
> what MUD programmers actually do mean by "inheritance".
> 
> Regarding academia's use of these terms, perhaps the 
> definitive document is 
> the Treaty of Orlando
> http://lieber.www.media.mit.edu/people/lieber/Lieberary/OOP/Tr
> eaty/Treaty.ps
> 
> 
> >In fact, I have thought about designs for a few programs for which
> >inheritance would make the system easier to understand and 
> maintain, [...]
> 
> I've got one for you: the shamefully undocumented CopyVisitor 
> from within 
> the E language implementation 
> http://www.erights.org/javadoc/org/erights/e/elang/visitors/Co
> pyVisitor.html .
> 
> Given a tree of typed nodes, such as Kernel-E parse trees, we 
> know that 
> we'll want to write several algorithms for walking such trees 
> and returning 
> similar trees derived from these trees by some 
> transformation.  The current 
> E language implementation has three such tree transformers: 
> RenameVisitor, 
> AlphaRenameVisitor, and SubstVisitor.  For all of these, for 
> most of the 
> types of parse nodes, they simply want to copy that parse node while 
> *filling in the likewise transformed version* of the children 
> of that parse 
> node.
> 
> The copying behavior they have in common is implemented by 
> the CopyVisitor.  
> The CopyVisitor is carefully written so that it can be reused in an 
> equivalent fashion whether by Java-style 
> class-based-inheritance, or by 
> E-style inheritance-by-static-delegation 
> http://www.erights.org/elang/blocks/inheritance.html .  
> 
> The familiar class-based description first:
> 
> The actual RenameVisitor is implemented in Java as a subclass of 
> CopyVisitor.  It overrides those methods it needs to change, 
> but not the 
> others.  For these others, CopyVisitor's copying behavior is 
> used, which 
> first *calls itself* to make a copy of the children of the node being 
> copied, and then makes a copy of the current node using these copied 
> children.  Of course, the "itself" above is actually a 
> RenameVisitor rather 
> than a pure CopyVisitor, so these children contain 
> transformed copies of the 
> original children.
> 
> The equivalent instance-based delegation description:
> 
> RenameVisitor could have been implemented in E as follows:
> 
>     def newRenameVisitor(renamings) :any {
>         def self := {
>             def super := newCopyVisitor(self)
> 
>             def RenameVisitor {
>                 to visitCatchExpr(...) :any { ... }
>                 //... likewise for all parse node types 
>                 //    needing transformation...
> 
>                 delegate { super }
>             }
>         }
>     }
> 
> CopyVisitor could have been implemented in E as:
> 
>     def newCopyVisitor(self) :any {
>         def CopyVisitor {
>             to visitCallExpr(recip, verb, args) :any {
>                 def transformedRecip := recip welcome(self)
>                 //... transform args ...
>                 newCallExpr(transformedRecip, verb, transformedArgs)
>             }
>             //... other parse node types ...
>         }
>     }
> 
> This can be seen as a combination of visitor and decoration, 
> or we can just 
> name this pattern "inheritance", since it exactly produces (with 
> instance-based delegation) the semantics associated with class-based 
> inheritance.
> 
> Given that we keep "delegate", notice how the "class" 
> construct provides us 
> no additional help with the above code.  Why?  Because 
> RenameVisitor is (in 
> Java terminology) concrete and final, while CopyVisitor is 
> essentially 
> abstract.  The class construct only helps in defining the 
> equivalent of 
> classes that are concrete and non-final.  The price of 
> leaving out the 
> "class" construct is only that it becomes four lines more 
> difficult to write 
> one object-maker that supports both direct instantiation and 
> inheriting (be 
> delegation) from the objects it creates.
> 
> Btw, many of us, when doing class-based programming with 
> inheritance, mostly 
> stopped using concrete non-final classes since the Udanax 
> Gold days.  When 
> we found we wanted to subclass a concrete class, we 
> refactored so that we 
> were subclassing from an abstract class.  I believe Dean was 
> always the 
> biggest advocate of this design rule.  The E implementation 
> grossly violates 
> this, but that's only because of Java used to have a horrendous huge 
> per-class memory cost.  (It may still, but we should fix this 
> anyway, since 
> memory is now cheaper.)
> 
> So my current inclination is to leave out the "class" 
> construct, go with 
> MarcS's definition of "inheritance", rather than Zooko's  and 
> to truthfully 
> observe that E supports inheritance perfectly well.  And then 
> expand on this 
> in the Walnut, including the qualifier about concrete 
> non-final classes.
> 
> 
> On a different and depressing note, in writing the above 
> code, I noticed a 
> reason not to use the "newThing" convention:  I first wrote
> 
>                 def newRecip := recip welcome(self)
> 
> and then I caught myself.  I think this mistake will always 
> be natural.  
> Better not to have a convention that conflicts with the above 
> line.  But I 
> really dislike "classThing".  I like "ThingClass" only 
> slightly better.  Are you 
> sure you don't like the current "ThingMaker"?  Instead of 
> either pretending 
> it's all just classes, or throwing them into the deep end of lambda 
> concepts, can't we introduce Makers by saying:
> 
> >Makers in E are like classes.  You define one as follows. 
> [all Makers have 
> >a "Maker" suffix on their name.]  You use one as follows:
> >
> >    def foo := ThingMaker(...)
> 
> 
> Only later need we reveal that the ThingMaker pattern is only 
> a pattern, not 
> class-like magic.
> 
> 
> 
>         Cheers,
>         --MarkM
> 
> _______________________________________________
> e-lang mailing list
> e-lang@mail.eros-os.org
> http://www.eros-os.org/mailman/listinfo/e-lang
>