简体   繁体   中英

Why can't I call a public method in the subclass from the superclass when the object is of the subclass type?

I have a class B that is a subclass of class A. I create an object of type B and call OnlyA() on it, but inside OnlyA() the call to OnlyB() causes a compiler error.

From my understanding, OnlyB() is the same as this.OnlyB() and the method called should be chosen from the object's class (B), not the current class where code is being executed (A). This is why the call to Both() calls the method in B, not A. So why is it searching for OnlyB() in A, not B? How am I supposed to know when the method called is chosen from the object's class or the current class?

class Program
{
    static void Main(string[] args)
    {
        B bRefB = new B();

        bRefB.OnlyA();
    }
}

class A
{
    public void OnlyA()
    {
        Console.WriteLine("In A - OnlyA()");
        OnlyB(); // compiler error
        Both();  // calls the method in B
    }

    public virtual void Both()
    {
        Console.WriteLine("In A - Both()");
    }
}

class B : A
{
    public void OnlyB()
    {
        Console.WriteLine("In B - OnlyB()");
    }

    public override void Both()
    {
        Console.WriteLine("In B - Both()");
    }
}

You are absolutely correct that OnlyB is the same as this.OnlyB . And that's the issue; this is of type A . It has no knowledge that B even exists (nor should it).

Superclasses do not, and are not supposed to, have any knowledge about the fact that they have derived classes at all let alone what methods are in them. Its not an issue of "searching"; what happens when you have C that doesn't define OnlyB ? What method would be called?

Subclasses on the other hand are always subclasses of the super class; and so it is safe for them to invoke base class methods.

Bradely's answer covers why your code does not work ( this is of type A ). Here is correct way to write your requirements as code.

You want to call method based on run-time type of an object. Since compile time of this is type of the current object you need to cast it in some way to derived type before calling. Possible options:

  • just cast - statically checked that B has OnlyB , cast exception at run-time:

     ((B)this).OnlyB(); 
  • use dynamic - no static type checking, exception at run time if actual class does not have OnlyB method irrespective if it is from B, C...

     dynamic b = this; b.OnlyB(); 
  • manual reflection call (same as dynamic ).

  • generics - see Curiously Recurring Template Pattern and generics constraints (C#)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM