class class1 { public void m() { Console.WriteLine("这是一个方法"); } public virtual void vm() { Console.WriteLine("这是一个虚方法"); } } class class2 : class1 { public new void m() { Console.WriteLine("这是继承类的方法"); } public override void vm() { //base.vm(); Console.WriteLine("这是继承类的虚方法"); } } class class3 : class2 { public new /*override*/ void vm() { //base.vm(); Console.WriteLine("这是第三个继承类的虚方法"); } } class Program { static void Main(string[] args) { class1 c1 = new class1(); c1.m(); c1.vm(); Console.WriteLine(); class2 c2 = new class2(); c2.m(); c2.vm(); Console.WriteLine(); class1 c3 = new class2(); c3.m(); c3.vm(); Console.WriteLine(); class3 c4 = new class3(); c4.m(); c4.vm(); Console.WriteLine(); class1 c5 = new class3(); c5.m(); c5.vm(); Console.ReadKey(); } }
/*
输出
这是一个方法
这是一个虚方法
这是继承类的方法
这是继承类的虚方法
这是一个方法
这是继承类的虚方法
这是继承类的方法
这是第三个继承类的虚方法
这是一个方法
这是继承类的虚方法
*/
问一下为什么c5.vm();输出的是”这是继承类的虚方法”?这个地方不太明白,还请高手能解释清楚一点,谢谢.
解决方案
2
去掉override就相当于new。
2
假如派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在 new 关键字一样执行操作。 ——摘自MSDN。
5
这个解释不了,要解释得花一大堆的口水
本人去看《你必须知道的.net》
http://www.cnblogs.com/anytao/archive/2007/09/10/must_net_15.html

看明白这个图,看明白继承后对象的内存分布和方法表怎么指向的
本人去看《你必须知道的.net》
http://www.cnblogs.com/anytao/archive/2007/09/10/must_net_15.html

看明白这个图,看明白继承后对象的内存分布和方法表怎么指向的
3
至于你那个疑问请百(谷)度(哥)“对象方法就近查找原则”
4
没有仔细看你的代码。不过告诉你一个原则,我们是严禁写 new 来重载方法的。假如你的 class3 明知道本人不是真正重写 vm方法,而是另起一个重名的私有方法,它还“装”什么vm方法,莫非你不知道为 class3 的那个私有方法起名为 vm2 或别的名字吗?
为什么明知道命名冲突,非要用new 语法来起一个重名的方法?
这个 new 语法是 c#的糟粕。是15年前从c++中学来的。他除了让你迷惑,没有任何真正的用处。
面相对象程序设计有“五大原则”,其中第一条原则就是说,子类所重写的 vm 方法必须能经过父类的测试环境去检验。例如信用卡假设分为3大类,每一大类都有一点区别,然后每一个大类又分为上百种小类。在编程开发中,每一种小类的信用卡,都应该能拿到通用的针对“信用卡”的测试机上测试通过。
假设一个信用卡有“可以当饼干吃”的新特性,它何必要取一个跟通用信用开的特性术语重名的名字来命名?仅仅为了显得本人“与别的信用卡有点不一样”吗?那也应该遵循继承、多态的基本原则啊?!
实际上 new 语法是 c# 代码中的糟粕。我们严禁写这种代码(而是要求你把 class3 的 vm 方法重新命名)。教科书上假如就事论事地简单介绍这个 new 语法、写了例子,然后了事,是对这个争议问题太不负责任了,对编程开发读者不负责任。原因是这个 new 是破坏面向对象基本原则的东西,是个很大的毛病,不是小问题。
为什么明知道命名冲突,非要用new 语法来起一个重名的方法?
这个 new 语法是 c#的糟粕。是15年前从c++中学来的。他除了让你迷惑,没有任何真正的用处。
面相对象程序设计有“五大原则”,其中第一条原则就是说,子类所重写的 vm 方法必须能经过父类的测试环境去检验。例如信用卡假设分为3大类,每一大类都有一点区别,然后每一个大类又分为上百种小类。在编程开发中,每一种小类的信用卡,都应该能拿到通用的针对“信用卡”的测试机上测试通过。
假设一个信用卡有“可以当饼干吃”的新特性,它何必要取一个跟通用信用开的特性术语重名的名字来命名?仅仅为了显得本人“与别的信用卡有点不一样”吗?那也应该遵循继承、多态的基本原则啊?!
实际上 new 语法是 c# 代码中的糟粕。我们严禁写这种代码(而是要求你把 class3 的 vm 方法重新命名)。教科书上假如就事论事地简单介绍这个 new 语法、写了例子,然后了事,是对这个争议问题太不负责任了,对编程开发读者不负责任。原因是这个 new 是破坏面向对象基本原则的东西,是个很大的毛病,不是小问题。
4
new 是掐断继承链条、只定义一个重名的私有方法的语法。而你的代码
public new /*override*/ void vm() { //base.vm(); Console.WriteLine("这是第三个继承类的虚方法"); }
这代码执行时的输出完全是本人骗本人。这里哪有继承了?这里明明是截断了继承,new 了一个新的重名的 vm 方法啊。所以你应该写
public new /*override*/ void vm() { //base.vm(); Console.WriteLine("这不是第三个继承类的虚方法,而是截断了继承之后的私有方法"); }
这样写代码,你调试时才不会被本人骗了。
3
c5 定义为 Class,所以它最终执行的是 class2 的 vm 方法。这个是很正常的。
无论怎么样你能看到,假如不写 new 则什么误会都不会有。class 完全可以将私有方法 vm 重新命名,没有必要重名、捣乱。
3
c5 定义为 class1,所以它最终执行的是 class2 的 vm 方法。这个是很正常的。
无论怎么样你能看到,假如不写 new 则什么误会都不会有。class3 完全可以将私有方法 vm 重新命名,没有必要重名、捣乱。
你本人在写 class3 的那个重名的私有方法 vm 内部的代码时若清醒一点,也会觉得这个 new 语法真的是给调试再捣乱,而并没有支持面向对象的继承和多态的基本机制。
无论怎么样你能看到,假如不写 new 则什么误会都不会有。class3 完全可以将私有方法 vm 重新命名,没有必要重名、捣乱。
你本人在写 class3 的那个重名的私有方法 vm 内部的代码时若清醒一点,也会觉得这个 new 语法真的是给调试再捣乱,而并没有支持面向对象的继承和多态的基本机制。
4
class1 c5 = new class3();
虽然你把他声明为 class1,但他(new class3())依然是 class3 类型
只是只能使用 class1 才有的属性和方法
class3.vm 是 new 的,自然不在 class1 中。因此就使用了 class2.vm
虽然你把他声明为 class1,但他(new class3())依然是 class3 类型
只是只能使用 class1 才有的属性和方法
class3.vm 是 new 的,自然不在 class1 中。因此就使用了 class2.vm
5
c1 = new class1();
自然 c1.vm() 是 class1 本人的
本人已经说了,虽然你把 c5 声明为 class1(那是原因是 class3 是 class1 子类,否则是要出错的),但并没有改变 c5 是 class3 本质
假如你不是 public new /*override*/ void vm()
而是 public override void vm()
的话,那就会是 Console.WriteLine(“这是第三个继承类的虚方法”); 了
而你现在的 public new void vm() 中,写到 Console.WriteLine(“这是第三个继承类的虚方法”); 反而是错误的
原因是这个 vm 方法不是继承来的,而是 class3 本人的(虽然和父类的 vm 方法重名)
自然 c1.vm() 是 class1 本人的
本人已经说了,虽然你把 c5 声明为 class1(那是原因是 class3 是 class1 子类,否则是要出错的),但并没有改变 c5 是 class3 本质
假如你不是 public new /*override*/ void vm()
而是 public override void vm()
的话,那就会是 Console.WriteLine(“这是第三个继承类的虚方法”); 了
而你现在的 public new void vm() 中,写到 Console.WriteLine(“这是第三个继承类的虚方法”); 反而是错误的
原因是这个 vm 方法不是继承来的,而是 class3 本人的(虽然和父类的 vm 方法重名)
5
原因是 class2 继承了 class1,并重写了 vm 方法
而 class3 继承了 class2,并覆盖了 vm 方法
由于 c5 实际上是 class3 类型,所以从 class1 的角度上看,只能看到 class2 重写的方法
这样能理解吗?
而 class3 继承了 class2,并覆盖了 vm 方法
由于 c5 实际上是 class3 类型,所以从 class1 的角度上看,只能看到 class2 重写的方法
这样能理解吗?