471,627 Members | 1,605 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,627 software developers and data experts.

Call root base method from doubly derived class?

Given

public class A {
virtual void foo() { ... }
}

public class B : A {
public override void foo() { ... }
public Bthingy() { ... base.foo() ...}
}

public class C : B {
public override void foo() { . . . }
public Cthingy() { ... base.foo() ... }
}
Bthingy's 'base.foo()' calls class A's foo.
Cthingy's 'base.foo()' calls class B's foo.

Is there a way for Cthingy to call the class A foo?

Dec 15 '05 #1
12 2523
DrBonzo,

No, there isn't. B would have to expose a method which would expose the
base method of A, without doing anything else.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"DrBonzo" <Dr*****@discussions.microsoft.com> wrote in message
news:73**********************************@microsof t.com...
Given

public class A {
virtual void foo() { ... }
}

public class B : A {
public override void foo() { ... }
public Bthingy() { ... base.foo() ...}
}

public class C : B {
public override void foo() { . . . }
public Cthingy() { ... base.foo() ... }
}
Bthingy's 'base.foo()' calls class A's foo.
Cthingy's 'base.foo()' calls class B's foo.

Is there a way for Cthingy to call the class A foo?

Dec 15 '05 #2
No.

"DrBonzo" <Dr*****@discussions.microsoft.com> wrote in message
news:73**********************************@microsof t.com...
Given

public class A {
virtual void foo() { ... }
}

public class B : A {
public override void foo() { ... }
public Bthingy() { ... base.foo() ...}
}

public class C : B {
public override void foo() { . . . }
public Cthingy() { ... base.foo() ... }
}
Bthingy's 'base.foo()' calls class A's foo.
Cthingy's 'base.foo()' calls class B's foo.

Is there a way for Cthingy to call the class A foo?

Dec 15 '05 #3

DrBonzo wrote:
Given

public class A {
virtual void foo() { ... }
}

public class B : A {
public override void foo() { ... }
public Bthingy() { ... base.foo() ...}
}

public class C : B {
public override void foo() { . . . }
public Cthingy() { ... base.foo() ... }
}
Bthingy's 'base.foo()' calls class A's foo.
Cthingy's 'base.foo()' calls class B's foo.

Is there a way for Cthingy to call the class A foo?


Directly? No. Indirectly? Sure.

public Cthingy()
{
A a = new A();
// Copy the parts of the C you want into the A
a.foo();
// Copy the parts back into C from the A.
}

Okay, yes, its dumb. But you can do it :)

Matt

Dec 15 '05 #4
Hi,

Nop, none

To C its parent is B + A + ... + Object; there is no distinction of where
a method was declared or how many times it was overriden. That's why it
access throug base and not with the class name.
cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation

"DrBonzo" <Dr*****@discussions.microsoft.com> wrote in message
news:73**********************************@microsof t.com...
Given

public class A {
virtual void foo() { ... }
}

public class B : A {
public override void foo() { ... }
public Bthingy() { ... base.foo() ...}
}

public class C : B {
public override void foo() { . . . }
public Cthingy() { ... base.foo() ... }
}
Bthingy's 'base.foo()' calls class A's foo.
Cthingy's 'base.foo()' calls class B's foo.

Is there a way for Cthingy to call the class A foo?

Dec 15 '05 #5
Hi,
public Cthingy()
{
A a = new A();
// Copy the parts of the C you want into the A
a.foo();
// Copy the parts back into C from the A.
}

Okay, yes, its dumb. But you can do it :)

This works in the case that A.foo is stateless ( do not change any member
variable) or if any changed member is accesible from C , if foo() change a
private member it will not work.

IMO this is a completely different situation that the one presented by the
OP. A derived class should not worry who of the ancesors override a method,
not should need to call a particular overriden method in the hierarchic
tree.

I would assume a bad design if this is the case.

any comments from the NG?
cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation

Dec 15 '05 #6

Ignacio Machin ( .NET/ C# MVP ) wrote:
Hi,
public Cthingy()
{
A a = new A();
// Copy the parts of the C you want into the A
a.foo();
// Copy the parts back into C from the A.
}

Okay, yes, its dumb. But you can do it :)

This works in the case that A.foo is stateless ( do not change any member
variable) or if any changed member is accesible from C , if foo() change a
private member it will not work.

IMO this is a completely different situation that the one presented by the
OP. A derived class should not worry who of the ancesors override a method,
not should need to call a particular overriden method in the hierarchic
tree.

I would assume a bad design if this is the case.

any comments from the NG?


Oh, I agree with you. I was just saying you CAN call the A::foo method
from
C. Its ugly, and it may or may not do what you want (you could easily
create a
method in A to deal with the state issues), but its really not OO at
all.

Matt

Dec 15 '05 #7
There was a discussion in this newsgroup over a year ago involving a
rather determined fellow who _swore_ that he had to do this. He decided
to write a tool that would alter the IL written by the compiler. I
don't know how that turned out (and I don't want to know--it was a
horrible idea).

The consensus at the time was that how you handle this situation
depends upon what it is you're trying to do, so with class names A, B,
and C, it's hard to say.

Typically, what's going on is that A's "foo" method (or property)
serves more than one purpose. The derived class B then overrides "foo"
in order to modify its behaviour, but in so doing makes it useful in
only one of the two possible contexts in which it can be used. C then
wants to call B's foo in one context, but in another context wants the
"other" way of using A's "foo", which B doesn't provide.

The solution is, as several here have pointed out, to create a new
method / property in B that exposes the functionality of "foo" for use
in that other context.

Now, the reason for all of the fancy language is that this all has to
do with semantics and design. What is "foo", exactly, and what is it
for? If it has two purposes, how would you name those? Let me give you
a concrete example. It may not be the best example going, but it serves
to illustrate the concept:

public class StockItem
{
public virtual decimal Price { get { ... }}
}

public class ImportedStockItem : StockItem
{
public override decimal Price { get { ... include import duties,
etc. ... }}
}

public class ImportedStockItemForInternalUse : ImportedStockItem
{
...
}

Yeah, I know: it's a stupid class hierarchy, but it's just for
illustration. What if, in class ImportedStockItemForInternalUse, you
needed to know the item's price before import duties, taxes, and other
stuff that was added in by the base class ImportedStockItem? How do you
get that?

You get that by realizing that StockItem.Price can be used for two
things in ImportedStockItemForInternalUse, and changing that class
accordingly:

public class ImportedStockItem : StockItem
{
public override decimal Price { get { ... include import duties,
etc. ... }}
public decimal PriceBeforeDutyAndTaxes { get { return base.Price;
}}
}

The point is that you expose base.Price as a second property (or
method), but with a name that explains why you're doing that, not with
some lame name like "BaseClassPrice". It's all about asking, "What does
this information mean, and why do I need it?"

Dec 15 '05 #8

"DrBonzo" <Dr*****@discussions.microsoft.com> wrote in message
news:73**********************************@microsof t.com...
Given

public class A {
virtual void foo() { ... }
}

public class B : A {
public override void foo() { ... }
public Bthingy() { ... base.foo() ...}
}

public class C : B {
public override void foo() { . . . }
public Cthingy() { ... base.foo() ... }
}
Bthingy's 'base.foo()' calls class A's foo.
Cthingy's 'base.foo()' calls class B's foo.

Is there a way for Cthingy to call the class A foo?


This is not possible in C# (which is a good thing IMO), only IL and C++/CLI
allows you to make static calls to virtual bases (provided your root base is
made non private).
Just curious, why you would need this for?

Willy.
Dec 15 '05 #9
Gee, thanks for the replies.

The answer is not unexpected, but disappointing anyway.

Interestingly, IntelliSense seems to know what I intend when I type
'base.base.',
but of course the compiler gags. Since there's only single inheritance,
this seems
like a fairly reasonable thing to want to do.

As for Willy's question, here's a silly graphical example - class A is a basic
square, say, and foo gets it drawn. Class B is a square with decorated
corners and B::foo (to mix metaphors) just draws the decoration.
Class C is a corner-decorated square with decorated center and
C::foo just draws the center decoration.

In my actual case, each class has its own additions to an XML document.

"DrBonzo" wrote:
Given

public class A {
virtual void foo() { ... }
}

public class B : A {
public override void foo() { ... }
public Bthingy() { ... base.foo() ...}
}

public class C : B {
public override void foo() { . . . }
public Cthingy() { ... base.foo() ... }
}
Bthingy's 'base.foo()' calls class A's foo.
Cthingy's 'base.foo()' calls class B's foo.

Is there a way for Cthingy to call the class A foo?

Dec 16 '05 #10
Given your graphical example, I would add another virtual method,
DrawEverything().

In the base class, it would look like this:

public virtual void DrawEverything()
{
foo();
}

In derived classes, it would look like this:

public override void DrawEverything()
{
base.DrawEverything();
foo();
}

Again, the method is named for the new functionality it provides: it
draws the entire figure. Each derived class is responsible for
overriding the method (if necessary) so that it continues to provide
that same functionality.

Dec 16 '05 #11
"DrBonzo" wrote:
Gee, thanks for the replies.

The answer is not unexpected, but disappointing anyway.

Interestingly, IntelliSense seems to know what I intend when I type
'base.base.',
but of course the compiler gags. Since there's only single inheritance,
this seems
like a fairly reasonable thing to want to do.

As for Willy's question, here's a silly graphical example - class A is a basic
square, say, and foo gets it drawn. Class B is a square with decorated
corners and B::foo (to mix metaphors) just draws the decoration.
Class C is a corner-decorated square with decorated center and
C::foo just draws the center decoration.

In my actual case, each class has its own additions to an XML document.


in your case, the proper way of override should be

B.foo does some extra work in addition to what A already does by calling
base.foo
C.foo does more extra work in addition to what B already does by calling
base.foo which through the transitive property of inheritance, will do what A
does as well.

with the proper inheritance, it's very rare that you would want to jump over
parent for grandparent functionaility. typically that's a indication of poor
design.
Dec 16 '05 #12
> with the proper inheritance, it's very rare that you would want to jump over
parent for grandparent functionaility. typically that's a indication of poor design.


Agreed, although in this case there's nothing wrong with providing two
methods: one that performs just the functionality provided by the
specific class, another that performs combined functionality all the
way up the hierarchy. It is conceivable that clients might need both
functions, but then that's exactly what they should be: two functions,
one purely local, the other calling recursively up the hierarchy.

Dec 16 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by Daniel Kay | last post: by
7 posts views Thread by relient | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.