从基类调用派生类的对象时,“this”关键字类型

时间:2015-04-24 22:00:10

标签: c# inheritance method-hiding

如果我有这样的话:

class Base
{
    public void Write()
    {
     if (this is Derived)
      {
         this.Name();//calls Name Method of Base class i.e. prints Base
        ((Derived)this).Name();//calls Derived Method i.e prints Derived 
      }
     else
      {
        this.Name();
      }
    }

    public void Name()
    {
        return "Base";
    }
}

class Derived : Base
{
    public new void Name()
    {
        return "Derived";
    }
}

并使用以下代码来调用它,

Derived v= new Derived();
v.Write(); // prints Base

然后调用基类的Name方法。但this方法中Write个关键字的实际类型是什么?如果它是Derived类型(因为Program控件进入Write方法中的第一个if块),那么它正在调用基本Name方法,为什么显式转换,{{ 1}},将调用更改为派生类的(Derived)this方法?

4 个答案:

答案 0 :(得分:5)

this将始终属于派生类类型。

调用this.Name();中调用基类Name()方法的原因是因为Name未定义为虚方法,因此在编译时将其链接到编译时对此时所拥有的this的实际类型一无所知。

关于上述代码的另外一个注释。通常在产品代码中明确引用Base类中的Derived类实际上是一种不好的做法,因为它破坏了Base类不应该知道继承它的类的OOP原则之一。但是,假设上面的代码仅用于C ++调查,那么这当然可以。

答案 1 :(得分:2)

如果要访问派生类中的任何重写成员,则应使用virtual和override:

class Base
{
    public void Write()
    {
     if (this is Derived)
      {
         this.Name();//calls Name Method of Base class i.e. prints Base
        ((Derived)this).Name();//calls Derived Method i.e prints Derived 
      }
     else
      {
        this.Name();
      }
    }

    public virtual void Name()
    {
        return "Base";
    }
}

class Derived : Base
{
    public override void Name()
    {
        return "Derived";
    }
}

答案 2 :(得分:1)

这就是你的全部需要。您不需要也不应该从基础检查类型来处理逻辑。应该在派生类中处理任何特殊逻辑,并且可能希望将方法标记为基础中的virtual和派生类中的override

class Base
{
    public void Write()
    {
        SomeWriteMethod(Name());
    }

    public virtual void Name()
    {
        return "Base";
    }
}

class Derived : Base
{
    public override void Name()
    {
        return "Derived";
    }
}

如果您想要Name()中的班级的实际名称,您只需要在基座中调用GetType().Name,它将自动适用于任何派生类,因为GetType()会返回给您实例的实例类型。就像GetType()属于实际实例一样,this也是您的实际实例,因此任何特殊逻辑都属于该类'实施

this实际上是基类中的冗余调用。您可以指定它,也可以不指定 - 您可以获得相同的结果。您看到混合结果的原因是您使用了new运算符。 new仅在使用该显式类型时有效。它基本上隐藏了链中的其他实现。因此,this位于Base的上下文中会让您的Base.Name()好像被覆盖一样,Derived.Name()会被使用。

MSDN: Knowing when to use override and new keywords

以下是关于new - Why does calling a method in my derived class call the base class method?

的优秀答案

答案 3 :(得分:0)

通过转换((Derived)this).Name(),您将显式设置为派生类。由于您在基类中定义了Write,因此将指向对它的方法调用。出现此问题的原因是您没有重写基本方法,而是从基类调用它。