D - Method Blocking
- Benji Smith (50/50) Aug 13 2003 Here's an idea that I've been aching for in several different
- Mike Wynn (52/102) Aug 13 2003 why make base::doSomthing public if you don't want it callable from a su...
- Jason Mills (6/26) Aug 13 2003 What about you are not the designer of the base class, and can't modify
- Benji Smith (65/69) Aug 13 2003 The example that I posted was a bit too simplistic. Let me tell you
- Patrick Down (4/34) Aug 13 2003 What happens when you do this:
- Mike Wynn (38/107) Aug 13 2003 class Node {}
- Benji Smith (38/67) Aug 14 2003 What I'd really like to do is to create a class hierarchy like this...
- Patrick Down (23/34) Aug 14 2003 Might be possible with templates
- Mike Wynn (81/153) Aug 14 2003 sub
- Sean L. Palmer (107/176) Aug 14 2003 Look at it this way.
- Philippe Mori (12/33) Aug 16 2003 In pratice, if someone want to block one method then the design is
Here's an idea that I've been aching for in several different languages: method blocking. I often create base classes that will have lots of different kinds of derived classes. To avoid duplicating code, I put all the method definitions in the base class, so that they can be inherited by the derived classes that really need them. But not all of the derived classes should have access to all of the methods in the parent class, and I'd like to block them. Take a look at this code: class baseClass { public void doSomething() { ... } public void doSomethingElse() { ... } } class derivedClassA: baseClass { public void doSomethingFun() { } } class derivedClassB: baseClass { block void doSomething(); public void doSomethingSilly() { } } In this example, my base class has two methods: "doSomething()" and "doSomethingElse()". The class derivedClassA inherits both of these virtual functions, but the class derivedClassB specifically blocks the use of the "doSomething()" function. Attempting to call this function should result in a compiler error, not in a runtime exception. In the past, I've used exceptions to define class hierarchies like this. I'll define the methods that I need in the base class, and then I'll overload those functions in the derived classes, something like this: class derivedClassB: baseClass { public void doSomething() { throw new Exception("Cannot call doSomething from a derivedClassB object"); } public void doSomethingSilly() { } } But throwing exceptions is costly, and besides, I should be able to know AT COMPILE TIME if I'm calling methods that shouldn't exist anyhow. I've been wishing for functionality like this for ages, and I can't fathom why it isn't available. It seems like it would be easy to use the "block" keyword to simply remove an entry from the v-table, wouldn't it?
Aug 13 2003
why make base::doSomthing public if you don't want it callable from a sub class ?? by saying class Base { public void func() {... } } you are defining the base "interface" of your object (java has the "final" keyword to stop you redefining a functions in a super class) but if you realy do no want func to be called for a super class I would say your object heirachy is wrong somewhere, or is should be class Base { private void func() {... } // only callable by Base and only implemented here } or protected if you want to allow the Derived classes to access them but not others. ----------------------------- import c.stdio; class A { this() { printf("A::this()\n"); } protected void show() { printf("A::show()\n"); } protected void shout() { printf("A::shout()\n"); } } class B : A { this() { printf("B::this()\n"); } public void show() { super.show(); printf("B::show()\n"); } } class C : A { this() { printf("C::this()\n"); } public void shout() { super.shout(); printf("C::shout()\n"); } } int main( char[][] args ) { A b = new B(); A c = new C(); b.show(); c.show(); /* // errr!!! was going to be B b = new B(); C c = new C(); b.show(); c.shout(); */ return 0; } ----------------------------------------- for some reason this works!! but a::show is protected so should only be accesable from sub class ?? sounds to me like you are trying to write code without thinking about the oo design of you classes. "Benji Smith" <dlanguage xxagg.com> wrote in message news:h2ikjv8f8bf6h09fnamt6ivuehqb5401vv 4ax.com...Here's an idea that I've been aching for in several different languages: method blocking. I often create base classes that will have lots of different kinds of derived classes. To avoid duplicating code, I put all the method definitions in the base class, so that they can be inherited by the derived classes that really need them. But not all of the derived classes should have access to all of the methods in the parent class, and I'd like to block them. Take a look at this code: class baseClass { public void doSomething() { ... } public void doSomethingElse() { ... } } class derivedClassA: baseClass { public void doSomethingFun() { } } class derivedClassB: baseClass { block void doSomething(); public void doSomethingSilly() { } } In this example, my base class has two methods: "doSomething()" and "doSomethingElse()". The class derivedClassA inherits both of these virtual functions, but the class derivedClassB specifically blocks the use of the "doSomething()" function. Attempting to call this function should result in a compiler error, not in a runtime exception. In the past, I've used exceptions to define class hierarchies like this. I'll define the methods that I need in the base class, and then I'll overload those functions in the derived classes, something like this: class derivedClassB: baseClass { public void doSomething() { throw new Exception("Cannot call doSomething from a derivedClassB object"); } public void doSomethingSilly() { } } But throwing exceptions is costly, and besides, I should be able to know AT COMPILE TIME if I'm calling methods that shouldn't exist anyhow. I've been wishing for functionality like this for ages, and I can't fathom why it isn't available. It seems like it would be easy to use the "block" keyword to simply remove an entry from the v-table, wouldn't it?
Aug 13 2003
Comments in line. Mike Wynn wrote:why make base::doSomthing public if you don't want it callable from a sub class ??What about you are not the designer of the base class, and can't modify it? For example, the base class could be a part of a library you are using. You want to specialize a class in the library but in such a way that some base methods just don't make sense anymore for the new subclass.by saying class Base { public void func() {... } } you are defining the base "interface" of your object (java has the "final" keyword to stop you redefining a functions in a super class) but if you realy do no want func to be called for a super class I would say your object heirachy is wrong somewhere, or is should be class Base { private void func() {... } // only callable by Base and only implemented here } or protected if you want to allow the Derived classes to access them but not others.
Aug 13 2003
On Wed, 13 Aug 2003 16:16:02 +0100, "Mike Wynn" <mike.wynn l8night.co.uk> wrote:why make base::doSomthing public if you don't want it callable from a sub class ??The example that I posted was a bit too simplistic. Let me tell you the real (well, almost real) situation in which I'm encountering this: ****************************************************************** class Node { public char[] name; public Node prevSibling; public Node nextSibling; public Node parent; public void appendChild(); public Node getChild(int index); public void removeChild(int index); } class Document: Node { public char[] version; public char[] encoding; public char[] standalone; block Node parent; } class Element: Node { public char[char[]][] attributes; } class Comment: Node { block void appendChild(); block void getChild(); block void removeChild(); } ****************************************************************** Comments, Elements, and Documents are all derived classes of the superclass Node. Documents and Elements both have children, so they both need the appendChild(), getChild, and removeChild() methods. But a comment node, which is a perfectly valid type of node, doesn't have any children, so it should be able to block these methods. It doesn't need them. Likewise, a Docment node can't have a parent, so I should be able to block the parent member. Of course, I could implement the appendChild(), removeChild(), and getChild() methods separately in both the Document class and in the Element class, but THE CODE IS ESSENTIALLY IDENTICAL, so it doesn't make any sense for me to have that code exist in both places. I moved that code to the parent class so that both derived classes can take advantage of it. And the Comment class need to descendants of the Node class, just like the Element and Document classes, so that I can handle them all polymorphically when linking to prevSibling and nextSibling. So, for my XML api, it would make my life a lot easier, it would make my object hierarchy simpler, and it would make runtime performance more predictable, if I could just block methods and members that aren't needed in a particular derived class.but if you realy do no want func to be called for a super class I would say your object heirachy is wrong somewhereI anticipated that type of response, but I think it's a knee-jerk reaction that isn't necessarily correct. That's like saying "if you have to ADD member functions to a child class, maybe the class hierarchy is wrong." A derived class can _ADD_ new members to the members inherited from the parent class. A derived class can _OVERRIDE_ existing members inherited from the parent class. So why can a derived class not _BLOCK_ access to some of the members of the parent class? This seems like a perfectly logical conclusion to me. There's no reason to say that the derived class isn't logically a subclass of the parent class. But it's not EXACTLY THE SAME as its parent, and one of the ways that it should be able to differentiate itself is by blocking access to methods that are important to the parent but not to the child. Am I the only one who thinks this is silly?
Aug 13 2003
In article <sivkjv0nadkrv2oebehn6c0fv33ebjdo1l 4ax.com>, Benji Smith says...On Wed, 13 Aug 2003 16:16:02 +0100, "Mike Wynn" <mike.wynn l8night.co.uk> wrote:What happens when you do this: Node n = new Comment(); n.appendChild(); // Legal for Nodewhy make base::doSomthing public if you don't want it callable from a sub class ??The example that I posted was a bit too simplistic. Let me tell you the real (well, almost real) situation in which I'm encountering this: ****************************************************************** class Node { public char[] name; public Node prevSibling; public Node nextSibling; public Node parent; public void appendChild(); public Node getChild(int index); public void removeChild(int index); } class Document: Node { public char[] version; public char[] encoding; public char[] standalone; block Node parent; } class Element: Node { public char[char[]][] attributes; } class Comment: Node { block void appendChild(); block void getChild(); block void removeChild(); }
Aug 13 2003
"Benji Smith" <dlanguage xxagg.com> wrote in message news:sivkjv0nadkrv2oebehn6c0fv33ebjdo1l 4ax.com...On Wed, 13 Aug 2003 16:16:02 +0100, "Mike Wynn" <mike.wynn l8night.co.uk> wrote:class Node {} class Doc : Node {} class NodeWithParent : Node { } class Foo : NodeWithParent { } etc or use interfaces; class Node { } interface IHasParent {} interface IHasSibling : IHasParent {} // how can you have siblings if you ain't got a parent interface IHasChildren {} // how can you have siblings if you ain't got a parent etc ... if you want to see the ways ppl solve this look at gui libs, (C++ : TurboVision,MFC, WTL, WxWindows, VGUI, BeOS API) (Delphi: VCL) (Java: AWT, Swing, IFC (if you can find it, was netscaps Swing before swing on top of the AWT, the Eclipse/IBM SWT) ) you have a similar issue, to the gui questions of ... should componant be able to "draw" on itself, and should it have children, and where if any do the layout managers connect to.why make base::doSomthing public if you don't want it callable from a sub class ??The example that I posted was a bit too simplistic. Let me tell you the real (well, almost real) situation in which I'm encountering this: ****************************************************************** class Node { public char[] name; public Node prevSibling; public Node nextSibling; public Node parent; public void appendChild(); public Node getChild(int index); public void removeChild(int index); } class Document: Node { public char[] version; public char[] encoding; public char[] standalone; block Node parent; } class Element: Node { public char[char[]][] attributes; } class Comment: Node { block void appendChild(); block void getChild(); block void removeChild(); } ****************************************************************** Comments, Elements, and Documents are all derived classes of the superclass Node. Documents and Elements both have children, so they both need the appendChild(), getChild, and removeChild() methods. But a comment node, which is a perfectly valid type of node, doesn't have any children, so it should be able to block these methods. It doesn't need them. Likewise, a Docment node can't have a parent, so I should be able to block the parent member. Of course, I could implement the appendChild(), removeChild(), and getChild() methods separately in both the Document class and in the Element class, but THE CODE IS ESSENTIALLY IDENTICAL, so it doesn't make any sense for me to have that code exist in both places. I moved that code to the parent class so that both derived classes can take advantage of it. And the Comment class need to descendants of the Node class, just like the Element and Document classes, so that I can handle them all polymorphically when linking to prevSibling and nextSibling. So, for my XML api, it would make my life a lot easier, it would make my object hierarchy simpler, and it would make runtime performance more predictable, if I could just block methods and members that aren't needed in a particular derived class.saybut if you realy do no want func to be called for a super class I wouldbecause your saying this is not quite a subclass! if you block a member it is no longer passable as its base class because it have missing functionality.your object heirachy is wrong somewhereI anticipated that type of response, but I think it's a knee-jerk reaction that isn't necessarily correct. That's like saying "if you have to ADD member functions to a child class, maybe the class hierarchy is wrong." A derived class can _ADD_ new members to the members inherited from the parent class. A derived class can _OVERRIDE_ existing members inherited from the parent class. So why can a derived class not _BLOCK_ access to some of the members of the parent class? This seems like a perfectly logical conclusion to me.There's no reason to say that the derived class isn't logically a subclass of the parent class. But it's not EXACTLY THE SAME as its parent, and one of the ways that it should be able to differentiate itself is by blocking access to methods that are important to the parent but not to the child. Am I the only one who thinks this is silly?no your just experiancing one of the problems with single inheritance and static typing, with MI or dynamic typing its all possible but the price is performance. "your object heirachy is wrong" may be a knee-jerk reaction, but you should question if your heirachy is right and why `Doc` can not have a parent (obviously there has to be a Node with a "null" parent, or no parent, which also means that it can not have any siblings too ) D has class invariants so Doc class must always have a null parent, all you have to do is put an assert in the "setParent method of Doc to make sure its parent can not be set, and write your code so that it can deal with getParent() returning null (i.e. no parent).
Aug 13 2003
On Wed, 13 Aug 2003 22:21:40 +0100, "Mike Wynn" <mike.wynn l8night.co.uk> wrote:"Benji Smith" <dlanguage xxagg.com> wrote in message news:sivkjv0nadkrv2oebehn6c0fv33ebjdo1l 4ax.com...What I'd really like to do is to create a class hierarchy like this... Node NodeWithChildren: Node NodeWithParent: Node Document:NodeWithChildren Element:NodeWithParent, NodeWithChildren Comment:NodeWithParent Text:NodeWithParent CDataSection:NodeWithParent ProcessingInstruction:NodeWithParent ...but it would require mulitiple inheritance, and apparantly it becomes much more difficult to write a compiler if it uses multiple inheritance. I suppose that NodeWithParent and NodeWithChildren could be interfaces (IHasParent and IHasChildren) rather than classes, but then I have to put the implementations of the parent-handling and children-handling methods into all of the individual classes. So, I would need to copy the parent-handling methods (which would be exactly the same in every class that uses them) five different times! The first rule of programming that I learned is DON'T HAVE THE SAME CODE IN MULTIPLE PLACES. I think that rule is more important than having a perfect object hierarchy. So interfaces are definitely a no-win situation for me. As far as I'm concerned interfaces are mostly useful when you need to enforce a particular set of methods onto other people who will be implementing classes that will interface with your code in a particular way. But using interfaces (in this situation) won't help ME keep my own code small, manageable, and robust.On Wed, 13 Aug 2003 16:16:02 +0100, "Mike Wynn" <mike.wynn l8night.co.uk> wrote:class Node {} class Doc : Node {} class NodeWithParent : Node { } class Foo : NodeWithParent { } etc or use interfaces; class Node { } interface IHasParent {} interface IHasSibling : IHasParent {} // how can you have siblings if you ain't got a parent interface IHasChildren {} // how can you have siblings if you ain't got a parent etc ...why make base::doSomthing public if you don't want it callable from a sub class ??"your object heirachy is wrong" may be a knee-jerk reaction, but you should question if your heirachy is right and why `Doc` can not have a parent (obviously there has to be a Node with a "null" parent, or no parent, which also means that it can not have any siblings too ) D has class invariants so Doc class must always have a null parent, all you have to do is put an assert in the "setParent method of Doc to make sure its parent can not be set, and write your code so that it can deal with getParent() returning null (i.e. no parent).It looks like I'll be sticking with my original strategy, throwing exceptions from the method implementations of descendant classes that shouldn't have those methods anyhow. So if you call... myComment.appendChild(myNode); ...it will throw a... DomException("You cannot call appendChild() from a Comment object"); It's ugly, and I don't like it, but at least it keeps me from copying the same code into five different classes. Honestly, there's got to be a better solution to this.
Aug 14 2003
In article <hh6njvsmtqduiuihdels8nrmvps8ju8p27 4ax.com>, Benji Smith says...What I'd really like to do is to create a class hierarchy like this... Node NodeWithChildren: Node NodeWithParent: Node Document:NodeWithChildren Element:NodeWithParent, NodeWithChildren Comment:NodeWithParent Text:NodeWithParent CDataSection:NodeWithParent ProcessingInstruction:NodeWithParent ...but it would require mulitiple inheritance...Might be possible with templates template AddParentT(T) { class WithParent : T { Node parent; } } template AddChildrenT(T) { class WithChildren : T { appendChild(); getChild() } } class Node {} class Document : instance AddChildrenT(Node).WithChildren {} class Element : instance AddParentT( instance AddChildrenT(Node).WithChildren).WithParent { } class Comment : instance AddParentT(Node).WithParent { } class Text : instance AddParentT(Node).WithParent { }
Aug 14 2003
"Benji Smith" <dlanguage xxagg.com> wrote in message news:hh6njvsmtqduiuihdels8nrmvps8ju8p27 4ax.com...On Wed, 13 Aug 2003 22:21:40 +0100, "Mike Wynn" <mike.wynn l8night.co.uk> wrote:sub"Benji Smith" <dlanguage xxagg.com> wrote in message news:sivkjv0nadkrv2oebehn6c0fv33ebjdo1l 4ax.com...On Wed, 13 Aug 2003 16:16:02 +0100, "Mike Wynn" <mike.wynn l8night.co.uk> wrote:why make base::doSomthing public if you don't want it callable from amixin's are what you want. you can use templates for "has children" or "group" class but D does not support lightwight templating (that is a template where the params are all objects so instances are all the same code (different cast on systems that require a cast like java) // you could try .. template has_children( Base : Node ) { class Group : Base, IGroup { add the child handleing code here. } } in d asfaik you have to use an interface for the group methods to gain acess to them as there is no way to cast to `Group` as you dont know the type it was created with a language feature that would help is lightweight templating, where the templated types are all Object (or restricted to a subclass of) and the compiler knows the type that the template related to (great for collections) so Stack<Node> is subclass of Stack<Object> which is a subclass of Stack. (like Java arrays are, [with the required runtime type checking compiled in automatically] kind of hybrid dynamic typechecking on a statically typed lang. the above example could be although code like lightweight_template(Base : Node) class Group : Base{ Node addChildren(); } } although there are issues here if you try to make a group of a group where as lightweight_template(Base : Node) class Owned : Node { Base getParent(); } } can be Owned<Owned<Doc>>What I'd really like to do is to create a class hierarchy like this... Node NodeWithChildren: Node NodeWithParent: Node Document:NodeWithChildren Element:NodeWithParent, NodeWithChildren Comment:NodeWithParent Text:NodeWithParent CDataSection:NodeWithParent ProcessingInstruction:NodeWithParent ...but it would require mulitiple inheritance, and apparantly it becomes much more difficult to write a compiler if it uses multiple inheritance. I suppose that NodeWithParent and NodeWithChildren could be interfaces (IHasParent and IHasChildren) rather than classes, but then I have to put the implementations of the parent-handling and children-handling methods into all of the individual classes. So, I would need to copy the parent-handling methods (which would be exactly the same in every class that uses them) five different times! The first rule of programming that I learned is DON'T HAVE THE SAME CODE IN MULTIPLE PLACES. I think that rule is more important than having a perfect object hierarchy.class Node {} class Doc : Node {} class NodeWithParent : Node { } class Foo : NodeWithParent { } etc or use interfaces; class Node { } interface IHasParent {} interface IHasSibling : IHasParent {} // how can you have siblings if you ain't got a parent interface IHasChildren {} // how can you have siblings if you ain't got a parent etc ...class ??So interfaces are definitely a no-win situation for me. As far as I'm concerned interfaces are mostly useful when you need to enforce a particular set of methods onto other people who will be implementing classes that will interface with your code in a particular way. But using interfaces (in this situation) won't help ME keep my own code small, manageable, and robust.should"your object heirachy is wrong" may be a knee-jerk reaction, but youwhichquestion if your heirachy is right and why `Doc` can not have a parent (obviously there has to be a Node with a "null" parent, or no parent,youalso means that it can not have any siblings too ) D has class invariants so Doc class must always have a null parent, allitshave to do is put an assert in the "setParent method of Doc to make sureas I said look at a few gui libs they all suffer from this exact problem, as do tree classes think about how to describe a binary tree each node, has two nodes left or right, which can be either a parent_node or a leaf_node; often you want a parent_node to only no data or a small amount of data a leaf is a node can not have children, but usually has a data item. its not perfect but what is ... but only requires the code writing once, instead of blocking the base class defines all the possible ops, but throws an exception if the sub class does not implemtent them (realy what is required is dynamic typing, but your using a statically types lang so you have to work around the problem) if you realy can't handle static typing, use perl, self or lua! class Node { Node getLeft() { throws NotValidOpException("can't do getLeft on this type"); } Node getRight() { throws NotValidOpException("can't do getRight on this type"); } void setLeft( Node n ) { throws NotValidOpException("can't do setLeft on this type"); } void setRight( Node n ) { throws NotValidOpException("can't do setRight on this type"); } int getType() { throws NotValidOpException("can't do getType on this type"); } Object getValue() { throws NotValidOpException("can't do getValue on this type"); } } class Parent : Node { Node l, r; Node getLeft() { return l; } Node getRight() { return r; } Node setLeft( Node n ) { l = n; } Node setRight( Node n ) { r = n; } } class Leaf : Node { int t; Object v; int getType() { return t; } Object getValue() { return v; } }parent can not be set, and write your code so that it can deal with getParent() returning null (i.e. no parent).It looks like I'll be sticking with my original strategy, throwing exceptions from the method implementations of descendant classes that shouldn't have those methods anyhow. So if you call... myComment.appendChild(myNode); ...it will throw a... DomException("You cannot call appendChild() from a Comment object"); It's ugly, and I don't like it, but at least it keeps me from copying the same code into five different classes. Honestly, there's got to be a better solution to this.
Aug 14 2003
Look at it this way. If you have this situation: class A { public foo() {} } class B : A { block foo() {} } void bar(A a) { a.foo(); } bar(new B); What do you suppose should happen? Are B's now no longer "compatible" with A's interface? If so, it isn't a "derived" class in the proper sense. Think what would happen if you "block" a member variable from class A in class B instead. The memory layout no longer matches, and anything expecting an A will probably fail if you give it a B instead. With methods, it will still break, but logically instead of physically. Deriving from a class is like a form of contract, demanding the child class remain compatible with the parent. You're asking to be able to violate that contract, and have the compiler figure it out and realize it can no longer be cast to the base class interface? If you just don't want to expose a base class member in the derived class, just redeclare it private (however in D you probably have to provide an implementation for it, probably should add a call to the super function so virtual calls thru the still-public parent interface work right). I do not think D automates this like C++ does. It seems to be a better solution would be mixins. ****************************************************************** class Parent { public void appendChild(); public Node getChild(int index); public void removeChild(int index); } class Child { public Node parent; } class Node { public char[] name; public Node prevSibling; public Node nextSibling; } class Document: Node, mixin Parent { public char[] version; public char[] encoding; public char[] standalone; } class Element: Node, mixin Parent, mixin Child { public char[char[]][] attributes; } class Comment: Node, mixin Child { } ****************************************************************** However you'd need a form of dynamic cast to decide if a given Node is capable of being a Parent, or being a Child. Walter seems against multiple inheritance, however, so I doubt anything like this will make it into D. However you can still do it "right" using good old fashioned class design. ;) ****************************************************************** class Node { public char[] name; public Node prevSibling; public Node nextSibling; } class ParentNode: Node { public void appendChild(); public Node getChild(int index); public void removeChild(int index); } class ChildNode : Node { public Node parent; } class ParentChildNode: ParentNode { public Node parent; } class Document: ParentNode { public char[] version; public char[] encoding; public char[] standalone; } class Element: ParentChildNode { public char[char[]][] attributes; } class Comment: ChildNode { } ****************************************************************** However as you can guess, this solution is brittle, since it takes work to keep the class hierarchy in good shape as its structure changes. You can see the beginnings of this in how I built ParentChildNode. Ideally ParentChildNode would be both a ParentNode *and* a ChildNode. It's a Pandora's Box. Sharing code seems like such a worthy cause, but it can cause lots of problems. Sean "Benji Smith" <dlanguage xxagg.com> wrote in message news:sivkjv0nadkrv2oebehn6c0fv33ebjdo1l 4ax.com...On Wed, 13 Aug 2003 16:16:02 +0100, "Mike Wynn" <mike.wynn l8night.co.uk> wrote:saywhy make base::doSomthing public if you don't want it callable from a sub class ??The example that I posted was a bit too simplistic. Let me tell you the real (well, almost real) situation in which I'm encountering this: ****************************************************************** class Node { public char[] name; public Node prevSibling; public Node nextSibling; public Node parent; public void appendChild(); public Node getChild(int index); public void removeChild(int index); } class Document: Node { public char[] version; public char[] encoding; public char[] standalone; block Node parent; } class Element: Node { public char[char[]][] attributes; } class Comment: Node { block void appendChild(); block void getChild(); block void removeChild(); } ****************************************************************** Comments, Elements, and Documents are all derived classes of the superclass Node. Documents and Elements both have children, so they both need the appendChild(), getChild, and removeChild() methods. But a comment node, which is a perfectly valid type of node, doesn't have any children, so it should be able to block these methods. It doesn't need them. Likewise, a Docment node can't have a parent, so I should be able to block the parent member. Of course, I could implement the appendChild(), removeChild(), and getChild() methods separately in both the Document class and in the Element class, but THE CODE IS ESSENTIALLY IDENTICAL, so it doesn't make any sense for me to have that code exist in both places. I moved that code to the parent class so that both derived classes can take advantage of it. And the Comment class need to descendants of the Node class, just like the Element and Document classes, so that I can handle them all polymorphically when linking to prevSibling and nextSibling. So, for my XML api, it would make my life a lot easier, it would make my object hierarchy simpler, and it would make runtime performance more predictable, if I could just block methods and members that aren't needed in a particular derived class.but if you realy do no want func to be called for a super class I wouldyour object heirachy is wrong somewhereI anticipated that type of response, but I think it's a knee-jerk reaction that isn't necessarily correct. That's like saying "if you have to ADD member functions to a child class, maybe the class hierarchy is wrong." A derived class can _ADD_ new members to the members inherited from the parent class. A derived class can _OVERRIDE_ existing members inherited from the parent class. So why can a derived class not _BLOCK_ access to some of the members of the parent class? This seems like a perfectly logical conclusion to me. There's no reason to say that the derived class isn't logically a subclass of the parent class. But it's not EXACTLY THE SAME as its parent, and one of the ways that it should be able to differentiate itself is by blocking access to methods that are important to the parent but not to the child. Am I the only one who thinks this is silly?
Aug 14 2003
"Benji Smith" <dlanguage xxagg.com> a écrit dans le message de news:h2ikjv8f8bf6h09fnamt6ivuehqb5401vv 4ax.com...Here's an idea that I've been aching for in several different languages: method blocking. I often create base classes that will have lots of different kinds of derived classes. To avoid duplicating code, I put all the method definitions in the base class, so that they can be inherited by the derived classes that really need them. But not all of the derived classes should have access to all of the methods in the parent class, and I'd like to block them. Take a look at this code: class baseClass { public void doSomething() { ... } } class derivedClassA: baseClass { public void doSomethingFun() { } } class derivedClassB: baseClass { block void doSomething(); }In pratice, if someone want to block one method then the design is probably bad... Also block a method does not works well with public inheritance since we can access the method with a base pointer but not a derived one. Thus, it would have to be combined with another inheritance (protected or private). I don't know if D check access after having found a method. If so then it would be usefull to have a modifier "hidden" so that the compiler would not consider the object as one of its base type (it would just allows overring virtual methods).
Aug 16 2003