Sketch of multiple inheritance in E

Kevin Reid <[email protected]>
Newsgroups gmane.comp.lang.e.general
Message-ID <[email protected]>
I just wrote <http://rosettacode.org/wiki/Multiple_inheritance#E>.

Quote: [[[

E does not have multiple inheritance as a built-in feature. In fact, E  
only has inheritance at all as a light syntactic sugar over delegation  
(message forwarding). However, using that facility it is possible to  
implement multiple inheritance.

This is a quick simple implementation of multiple inheritance. It  
simply searches (depth-first and inefficiently) the inheritance tree  
for a method; it does not do anything about diamond inheritance. These  
shortcomings could be fixed if more powerful multiple inheritance were  
needed.

]]]

(Fixing diamond inheritance is a little bit tricky, because it means  
that if you have A isa B isa D and A isa C isa D, then B's behavior  
(whether its super-call goes to D or C) has to depend on the existence  
of C, which is not part of B's definition. However, I believe this is  
*possible*, in a safe way, because B has the "self" reference, which  
is the authority on how the composite object should behave.)

[[[

def minherit(self, supers) {
     def forwarder match [verb, args] {
         escape __return {
             if (verb == "__respondsTo") {
                 def [verb, arity] := args
                 for super ? (super.__respondsTo(verb, arity)) in  
supers {
                     return true
                 }
                 return false
             } else if (verb == "__getAllegedType") {
                 # XXX not a complete implementation
                 return supers[0].__getAllegedType()
             } else {
                 def arity := args.size()
                 for super ? (super.__respondsTo(verb, arity)) in  
supers {
                     return E.call(super, verb, args)
                 }
                 throw(`No parent of $self responds to $verb/$arity`)
             }
         }
     }
     return forwarder
}

The task example:

def makeCamera(self) {
     return def camera extends minherit(self, []) {
         to takesPictures() { return true }
     }
}

def makeMobilePhone(self) {
     return def mobilePhone extends minherit(self, []) {
         to makesCalls() { return true }
         to internalMemory() { return 64*1024 }
     }
}

def makeCameraPhone(self) {
     return def cameraPhone extends minherit(self, [
         makeCamera(self),
         makeMobilePhone(self),
     ]) {
         to internalMemory() {
             return super.internalMemory() + 32 * 1024**2
         }
     }
}

And testing that it works as intended:

? def p := makeCameraPhone(p)
 > [p.takesPictures(), p.makesCalls(), p.internalMemory()]
# value: [true, true, 33619968]

]]]

-- 
Kevin Reid                            <http://homepage.mac.com/kpreid/>




-- 
Kevin Reid                            <http://homepage.mac.com/kpreid/>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.