父类:
class TestBase
{
public string name="Aa";
public string GetName()
{
return this.name;
}
}
子类:
class Test : TestBase
{
public new string name = "Bb";
}
在页面中调用子类:
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Test t = new Test();
Response.Write(t.GetName());
}
}
请问是输出结果是 “Aa” 还是 “Bb”?给出解释,谢谢!
输出的结果是:Aa。
原因:
被new限定符重新定义的对象(属性、变量、方法、事件等等)的有效域为新定义的类及其派生类。当你在Test里使用new操作符重新定义变量name的时候,在基类调用的GetName方法是看不到这个新定义的。
如果你有内存地址分配的基础知识就不难理解了:
定义一个变量,实际上是在内存分配了一个地址空间,然后通过这个变量名(符号)去连接地址空间。
在基类里,变量name这个符号的地址空间对应的内容是是Aa,GetName方法就使用这个地址空间的内容进行输出的。
而在派生类里,新分配了一个地址空间,同时把变量符号name指向了新分配的地址空间,从而隐藏了原来的name对应的地址空间,此时,name对应的值也就变成了Bb了。
当在派生类里调用GetName的方法的时候,由于方法GetName是在基类定义的,因此使用的还是基类的变量,但假如你对GetName方法重新定义,则不同了:
public class Test : TestBase
{
public new string GetName()
{
return name;
}
}
然后:
Test t = new Test();
string v1 = t.GetName();
string v2 = (t as TestBase).GetName();
这个输出的结果是:v1为Bb,v2为Aa。
换个方式,把GetName定义为虚拟函数:
public virtual string GetName()
{
return name;
}
public class Test : TestBase
{
public override string GetName()
{
return name;
}
}
然后在派生类里对这个方法重载,输出的结果则都是Bb。
当然,如果把GetName的重载写成:
public override string GetName()
{
return base.GetName();
}
或者写成
public override string GetName()
{
return base.name;
}
或者写成
public new string GetName()
{
return base.name;
}
输出的则又是Aa了。
以上回答有点冗长罗索,希望能对你有帮助。
显然是Aa。要点就是对于this的理解,this表示当前实例,它的类型是当前所在class的类型。因此这里访问的是TestBase里的name。你这么看就很清楚了:
class TestBase
{
public string name = "Aa";
public string GetName()
{
return (this as TestBase).name;
}
}
同意。
public class TestBase
{
public string name="Aa";
public string GetName()
{
return name;
}
}
public class Test : TestBase
{
// public new string name = "Bb";
public string GetName()
{
return name;
}
}
最好理解一下类的执行顺序。