www.digitalmars.com         C & C++   DMDScript  

D - Method Blocking

reply Benji Smith <dlanguage xxagg.com> writes:
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
next sibling parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
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
next sibling parent Jason Mills <jmills cs.mun.ca> writes:
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
prev sibling parent reply Benji Smith <dlanguage xxagg.com> writes:
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 somewhere
I 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
next sibling parent Patrick Down <Patrick_member pathlink.com> writes:
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:

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(); }
What happens when you do this: Node n = new Comment(); n.appendChild(); // Legal for Node
Aug 13 2003
prev sibling next sibling parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
"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 a sub
class ??
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.
 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 somewhere
I 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.
because 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.
 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
parent reply Benji Smith <dlanguage xxagg.com> writes:
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...
 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 ??
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 ...
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.
"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
next sibling parent Patrick Down <Patrick_member pathlink.com> writes:
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
prev sibling parent "Mike Wynn" <mike.wynn l8night.co.uk> writes:
"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:

"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 a
sub
class ??
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 ...
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.
mixin'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>>
 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.

"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.
as 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; } }
Aug 14 2003
prev sibling parent "Sean L. Palmer" <palmer.sean verizon.net> writes:
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:

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 somewhere
I 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
prev sibling parent "Philippe Mori" <philippe_mori hotmail.com> writes:
"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