[英]Will GetType() return the most derived type when called from the base class?
[英]“this” keyword type when called on an object of derived class from base class
如果我有这样的事情:
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
方法。 但是在Write
方法中this
关键字的实际类型是什么? 如果那是Derived
类型的(由于Program控件在Write
方法中输入第一个if块),则它正在调用基本Name
方法,为什么显式强制转换(Derived)this
,将对调用的Name
方法进行更改类?
this
将始终是派生类类型。
之所以调用this.Name();
调用基类Name()
方法是因为Name
没有被定义为一个虚拟的方法,因此它是在编译时被链接时,编译器知道任何关于实际类型的this
它将拥有在这一点上。
关于以上代码的另一注。 通常,在产品代码中,显式地引用Base类的Derived类确实是一种不好的做法,因为它违反了OOP原则之一,即,Base类不应该知道继承该类的类。 但是,假设上面的代码仅用于C ++研究,那当然可以。
如果要访问派生类中的所有重写成员,则应使用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";
}
}
这就是您的全部需求。 您不需要也不应该从基础检查类型来处理逻辑。 任何特殊的逻辑都应在派生类中处理,并且可能希望在基类中将方法标记为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().Name
,它将自动适用于任何派生类,因为GetType()
返回您实例的实际实例类型。 就像GetType()
是实际实例一样, this
也是您的实际实例,因此任何特殊逻辑都将属于该类的实现。
this
实际上是基类中的多余调用。 您可以指定它,也可以不指定它,否则会得到相同的结果。 您看到混合结果的原因是因为您使用了new
运算符。 仅当使用该显式类型时, new
才有效。 它基本上隐藏了链中的其他实现。 因此,在Base
上下文中, this
将为您提供Base.Name()
,就像您已被覆盖一样,将使用Derived.Name()
代替。
这是关于new
一个很好的答案- 为什么在派生类中调用方法会调用基类方法?
通过强制转换((Derived)this).Name()
,可以将其显式设置为派生类。 由于您在基类中定义了Write
,因此这将指向方法调用。 发生此现象的原因在于,您没有重写基方法,而是从基类中调用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.