- From: liorean <liorean@gmail.com>
- Date: Wed, 6 Jun 2007 10:50:45 +0200
- To: public-webapi@w3.org
On 06/06/07, Cameron McCormack <cam@mcc.id.au> wrote: > What should the prototype chain for an object that implements multiple > interfaces looks like? A single interface is simple enough: > > NodeList = { an object } > NodeList.[[Prototype]] = Object prototype object > NodeList.prototype = { an object } > NodeList.prototype.[[Prototype]] = Object prototype object > NodeList.prototype.constructor = NodeList > NodeList.prototype.someFunction = { some function } Well, if there is no [[Construct]] property on the NodeList that is callable using new NodeList I don't think the NodeList.prototype.constructor property should point to the NodeList object. If there is a constructor that is callable in that way then let it point there. If there is no such constructor then there should not be a NodeList.prototype.constructor property. Also I think you forgot two things: NodeList.[[Class]] = "Object" NodeList.prototype.[[Class]] = "NodeList" (The ECMAScript built-in constructors all follow the pattern of having [[Call]], so their [[Class]] is "Function" instead and their [[Prototype]] is the initial Function.prototype. The DOM constructors don't have [[Call]] so their [[Class]] should be "Object" instead. Or some implementation specific value, but if we're specifying things that are not interoperable anyway I think we can at least do the sensible thing.) > nl = { an object } > nl.[[Prototype]] = NodeList.prototype and nl.[[Class]] = "NodeList" > What happens if an object implements multiple interfaces, e.g. an > Element that is also an EventTarget? I can imagine a way to handle this > with prototypes, for example: > > Node = { an object } > Node.[[Prototype]] = Object prototype object > Node.prototype = { an object } > Node.prototype.constructor = Node Again Node.[[Class]] = "Object" And it doesn't make sense to have a Node.prototype.constructor which is not a constructor. But I'll stop repeating that for every case now. > Element = { an object } > Element.[[Prototype]] = Object prototype object > Element.prototype = { an object } > Element.prototype.[[Prototype]] = Node.prototype > Element.prototype.constructor = Element > > EventTarget = { an object } > EventTarget.[[Prototype]] = Object prototype object > EventTarget.prototype = { an object } > EventTarget.prototype.constructor = EventTarget > > elt = { an object } > elt.[[Prototype]] = { an object } > elt.[[Prototype]].[[Prototype]] = null > elt.[[Prototype]].[[Get]](P): > 1. If O doesn't have a property with name P, go to step 4. > 2. Get the value of the property. > 3. Return Result(2). > 4. Call the [[HasProperty]] method of the Element prototype > object. > 5. If Result(4) is true, go to step 9. > 6. Call the [[HasProperty]] method of the EventTarget prototype > object. > 7. If Result(6) is true, go to step 11. > 8. Return undefined. > 9. Call the [[Get]] method of the Element prototype object. > 10. Return Result(9). > 11. Call the [[Get]] method if the EventTarget prototype object. > 12. Return Result(11). > > The same question could apply to multiple inheritance (which is allowed > by OMG IDL, but AFAIK is not used in any of the DOM specs). Several interfaces may be implemented on the same object. In this case, I suspect the browsers would be implementing the EventTarget interface on the Element interface object, or the Node interface object. But yes, I can see how it would make sense to be able to chain together inheritance like that, so that if a property was added to either the EventTarget or the Element prototypes it was still accessible from the object that implements both. > This is probably not what browsers do in practice, though. For example, > Opera 9 has an addEventListener method directly on the Node interface > prototype object (see http://mcc.id.au/2007/05/binding-tests/#t008), > presumably because all Node objects in a document also implement > EventTarget. > > Any opinions on how to specify this? I'd wish to say I had a reasonable opinion. I do have an idea about it that is very similar to yours, but that would require a chaining together of prototype chains, which likely would mean that the multiple multilevel inheritance problem would have to be solved. I doubt we'd want to go into that. But if we indeed do want to go into that, the Python model makes best sense of all I've see so far. Just use it for prototypes instead of classes. The inheritance list itself doesn't have to be runtime resolved since it only applies to the DOM and not any ES objects, implementations would probably hardcode it for performance reasons. <uri:http://www.python.org/download/releases/2.3/mro/> Another possible way to go: Something that might make sense is to conflate all the interfaces for something into a single inheritance object delegation chain. E.g. an implementation could have all of Document, DocumentLS, DocumentStyle etc. conflated into the Document interface object so that the document only has a single prototype object to delegate to. The obvious problem to this is that an implementation then wouldn't be able to contain more than one simultaneous Document implementation. -- David "liorean" Andersson
Received on Wednesday, 6 June 2007 08:50:51 UTC