问题
If I have something like this:
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";
}
}
and use the following code to call it,
Derived v= new Derived();
v.Write(); // prints Base
then the Name
method of base class gets called. but what would be the actual type of this
keyword in the Write
method? if that is of Derived
type(as the Program control enters the first if block in Write
method) then it is calling the base Name
method, and why does the explicit casting,(Derived)this
, change the call to the Name
method of derived class?
回答1:
this
will always be of the derived class type.
The reason why in the call this.Name();
calls the base class Name()
method is because Name
is not defined as a virtual method, thus it is being linked in compile time when the compiler knows nothing about the actual type of this
that it will have at this point.
One more note regarding the code above. Generally in product code referring to a Derived class from the Base class explicitly is really a bad practice as it breaks one of the OOP principles that the Base class should not be aware about the classes which inherit it. However, assuming that the code above was just used for C++ investigation then this is of course ok.
回答2:
You should be using virtual and override if you want to access any overridden members in a derived 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 virtual void Name()
{
return "Base";
}
}
class Derived : Base
{
public override void Name()
{
return "Derived";
}
}
回答3:
This is all your need. You do not need to and should not be checking the type from the base to handle logic. Any special logic should be be handled in the derived classes and probably want to mark methods up as virtual
in the base and override
in the derived classes.
class Base
{
public void Write()
{
SomeWriteMethod(Name());
}
public virtual void Name()
{
return "Base";
}
}
class Derived : Base
{
public override void Name()
{
return "Derived";
}
}
If you want the actual name of the class in Name()
, you just need to call GetType().Name
in the base and it will automatically work for any derived classes as GetType()
returns you the actual instanced type of the instance. Just like GetType()
is of the actual instance, this
is also your actual instance so any special logic will be of that class' implementation.
this
is actually a redundant call in your base class. Either you specify it or you don't -- you get the same result. The reason you see mixed results is because you used the new
operator. new
only works when you are working with that explicit type. It basically hides other implementations in the chain. And so, this
being in the context of Base
is going to give your Base.Name()
where as if you had overridden, Derived.Name()
would have been used instead.
MSDN: Knowing when to use override and new keywords
Here is an excellent answer about new
-- Why does calling a method in my derived class call the base class method?
回答4:
By casting ((Derived)this).Name()
, you are explicitly setting it to the derived class. Since you have Write
defined in the base class, this will point method calls to it. This behavior occurs because you have not overridden the base method and you are calling it from the base class.
来源:https://stackoverflow.com/questions/29858243/this-keyword-type-when-called-on-an-object-of-derived-class-from-base-class