当对象属于子类类型时,为什么我不能从超类中调用子类中的公共方法?

时间:2017-06-29 20:52:09

标签: c# inheritance

我有一个类B,它是类A的子类。我创建了一个类型为B的对象并在其上调用了OnlyA(),但在OnlyA()内部,对OnlyB()的调用会导致编译器错误。

根据我的理解,OnlyB()this.OnlyB()相同,并且应该从对象的类(B)中选择调用的方法,而不是当前正在执行代码的类(A)。这就是为什么对Both()的调用调用B中的方法而不是A.那么为什么它在A中搜索OnlyB()而不是B?我怎么知道从对象的类或当前类中选择调用的方法?

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()");
    }
}

2 个答案:

答案 0 :(得分:4)

OnlyBthis.OnlyB相同,这是绝对正确的。这就是问题所在; this的类型为A。它不知道B甚至存在(也不应该存在)。

Superclasses不会,也不应该知道他们已经派生了这一事实,更不用说它们中包含哪些方法了。它不是"搜索&#34 ;;当C没有定义OnlyB时会发生什么?会叫什么方法?

另一方面,子类总是超类的子类;因此,他们可以安全地调用基类方法。

答案 1 :(得分:1)

Bradely answer涵盖了您的代码无效的原因(<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 805 314" style="enable-background:new 0 0 805 314;" xml:space="preserve"> <style type="text/css"> .st0{fill:#3B97D3;stroke:#000000;stroke-miterlimit:10;} .st1{fill:#F1F2F2;stroke:#000000;stroke-miterlimit:10;} .st2{fill:#E6E7E8;stroke:#000000;stroke-miterlimit:10;} .st3{fill:#FFFFFF;stroke:#000000;stroke-miterlimit:10;} .st3{ transform-origin:55% 50%; -moz-transform-origin:55% 50%; animation: flipX 1.6s forwards; } @-webkit-keyframes flipX { 0% { opacity:0; -webkit-transform: perspective(400px) translateZ(0) rotateX(0) scale(1); transform: perspective(400px) translateZ(0) rotateY(0) scale(1); } 100% { opacity:1; -webkit-transform: perspective(400px) translateZ(0) rotateX(180deg) scale(1); transform: perspective(400px) translateZ(0) rotateX(180deg) scale(1); } } @keyframes flipX { 0% { opacity:0; -webkit-transform: perspective(400px) translateZ(0) rotateX(0) scale(1); transform: perspective(400px) translateZ(0) rotateX(0) scale(1); } 100% { opacity:1; -webkit-transform: perspective(400px) translateZ(0) rotateX(180deg) scale(1); transform: perspective(400px) translateZ(0) rotateX(180deg) scale(1); } } .flipX{ opacity:0; -webkit-animation: flipX 2s cubic-bezier(0.2, 0.3, 0.25, 0.9) forwards; animation: flipX 2s cubic-bezier(0.2, 0.3, 0.25, 0.9) forwards; } </style> <g id="Layer_1"> <rect id="XMLID_42_" class="st0" width="805" height="314"/> </g> <g id="Layer_2"> <rect id="XMLID_1_" x="55" y="129" class="st1" width="192" height="98"/> <g id="Layer_3"> <polyline id="XMLID_43_" class="st2" points="55,129 151,178 247,129 "/> <polyline id="XMLID_3_" class="st3" points="55,129 151,64 247,129 "/> </g> </g> </svg>类型为this)。以下是将您的需求编写为代码的正确方法。

您希望根据对象的运行时类型调用方法。由于A的编译时间是当前对象的类型,因此在调用之前需要以某种方式将其强制转换为派生类型。可能的选择:

  • 刚刚施放 - 静态检查B有this,在运行时施放异常:

    OnlyB
  • 使用((B)this).OnlyB(); - 没有静态类型检查,如果实际的类没有dynamic方法,则在运行时异常,无论它是否来自B,C ......

    OnlyB
  • 手动反射调用(与dynamic b = this; b.OnlyB(); 相同)。

  • 泛型 - 请参阅Curiously Recurring Template Pattern and generics constraints (C#)