Suppose that class A inherits from class B which in turn inherits from class C. Now suppose that a virtual method void f() has been defined in A, which is overridden in both B and C. Calling B.f() from any method in A can be done by simply using base.f(). What about calling C.f() from a method in A?
-
4Possible duplicate: http://stackoverflow.com/questions/1006530/c-how-to-call-a-second-level-base-class-method-like-base-base-gethashcode – itowlson Dec 04 '09 at 00:32
-
I assume you mean calling A.f() from a method in C ? – Thomas Levesque Dec 04 '09 at 00:34
-
I am really just guessing, but can't you cast `this` to C? ((C)this).f(); – Michael Stum Dec 04 '09 at 00:46
9 Answers
Generally, by overriding a class, you are accepting that it provides the interface and some of the behavior you want. A shouldn't know about it's super-superclass unless explicitly exposed in some way by its superclass. This is actually desirable, because you don't need to know how C is implemented when you subclass B. You shouldn't even know that C is involved.
If b's f() calls base.f(), a's base.f() just needs to call its own base.f() and you're done. If it doesn't, the only way to do that yourself is through intrusive methods based on Reflection. If you find yourself needing to do this, you've probably got an error in your design (violating the Law of Demeter, for one).

- 19,244
- 4
- 34
- 61
-
thanks, it's not my own design. in this case class B and C are Telerik components. Class B provides most of the functionality I needed, but to implement some of the functionality I needed to call methods in C. – sisis Apr 02 '10 at 18:17
You can, through reflection, or with IL code generation. Other than that, you can't, and you really shouldn't, this doesn't sound like good design.
When you override a method in OOP, you basically say that "for this type, this method will replace the old method", with the provision that you can, if necessary (and typically it is), call the replaced (overridden) method.
However, you can't skip a level directly, unless you resort to reflection or IL trickery, and there's a good reason for that. If the intermediate class should allow you to skip it for this method call, you should add a special method to it that you can use. The reason this is "hard" to do is that you typically shouldn't be doing it, you should always go to the next level up, so that it can stay in control.

- 380,855
- 102
- 628
- 825
This can be done through reflection. You get the Type of the current class, use that to get the parent type, and then get the parent type of the parent type.
The reason it is not supported directly in the language is that it breaks the abstraction model of inheritance. It's not really compatible with conventional object-oriented design.

- 5,744
- 2
- 29
- 45
I assume you mean calling A.f() from a method in C ?
Short answer : you can't
However, if you have control over B, you could add a method to B to call its base explicitly :
protected void BaseF()
{
base.f();
}
And then call that method from C

- 286,951
- 70
- 623
- 758
Try this:
C c = this;
c.f();
This prints "C":
public static void Main()
{
A o = new A();
Console.WriteLine(o.f());
}
class C
{
public virtual string f()
{
return "C";
}
}
class B : C
{
public virtual string f()
{
return "B";
}
}
class A : B
{
public virtual string f()
{
C c = this;
return c.f();
}
}

- 28,040
- 10
- 64
- 64
-
That doesn't appear to compile (when I try it anyway). Are you thinking of C++, which *does* have a similar syntax for calling methods further up the inheritance chain? – itowlson Dec 04 '09 at 00:36
-
This does not compile, nor work in theory, you can not call methods like that unless they are static, in which case they can't be virtual. – Lasse V. Karlsen Dec 04 '09 at 00:40
-
Sorry, I did have a momentary C++ lapse in judgement. Edited with a workaround. – Jason Dec 04 '09 at 03:04
From the function in C, you can call base.f(), and this is what you should do. If B.f() (which is what you are effectively calling) chooses to also call base.f(), then that achieves what you want, but it is totally up to the implementation of B as to wehther that happens or not.
You can try casting C as A and the calling f(), like this:
public class C : B {
public override f() {
((A) this).f();
}
}
but the problem with this is that C has no idea where f() is declared - all it knows is that there is an implementation of it in B which can be overridden, C has no clue that A exists. The above sample is actually a bad piece of code, and will produce a compile time error if A does not implement f().

- 49,403
- 14
- 95
- 145
Use new
rather than override
is one way (the function doesn't need to be virtual to use new
although it can be).
This may give you some other issues though. If you up-cast MyClass
to MyBaseClass
anywhere it will use the MyBaseClass
version of the function.
private void Form1_Load(object sender, EventArgs e)
{
var mc = new MyClass();
mc.Foo();
((MyBaseClass) mc).Foo();
}
public class MyBaseClass
{
public virtual void Foo ()
{
Console.WriteLine("Calling from MyBaseClass");
}
}
public class MyClass : MyBaseClass
{
new public void Foo ()
{
Console.WriteLine("Calling from MyClass");
}
}
the output you get is:
Calling from MyClass
Calling from MyBaseClass
As was commented earlier, Virtual can never be overridden in this way, and you must use 'new' instead of 'override'.
Here's an example using your class names:
This is not a good practise, as it gets extremely confusing and breaks much of the expected inheritence behavior, and the 'new' keyword is intended to force a new interface item onto a class that did not intend being overridden.
Cheers, Jason
class Program
{
static void Main(string[] args)
{
C c = new C();
A a = new A();
a.DoThis();
Console.ReadKey();
}
}
public class C
{
public virtual void DoThis() {
Console.WriteLine("In C"); }
}
public class B : C
{
public new void DoThis()
{
Console.WriteLine("In B");
}
}
public class A : B
{
public new void DoThis()
{
Console.WriteLine("In A..");
((C) this).DoThis();
}
}

- 31
- 2
This seems like a design issue.
A couple of options you have:
- Take the bulk of A.DoThis(), and move it to another method (protected?) called something appropriate (DoThat()?). Now, you can call it directly.
- Split up your object, and consider using composition rather than inheritance to reuse behavior.

- 12,848
- 2
- 29
- 33