代码:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 BaseClass bc1 = new SubClass1(); 6 BaseClass bc2 = new SubClass2(); 7 SubClass1 sc1 = new SubClass1(); 8 SubClass2 sc2 = new SubClass2(); 9 10 bc1.Prinf(); 11 bc2.Prinf(); 12 sc1.Prinf(); 13 sc2.Prinf(); 14 } 15 } 16 17 abstract public class BaseClass 18 { 19 public virtual void Prinf() 20 { 21 Console.WriteLine("虚方法"); 22 } 23 } 24 25 class SubClass1 : BaseClass 26 { 27 public override void Prinf() 28 { 29 Console.WriteLine("重写方法"); 30 } 31 } 32 33 class SubClass2 : BaseClass 34 { 35 public new void Prinf() 36 { 37 Console.WriteLine("新方法"); 38 } 39 }
BaseClass bc2 = new SubClass2(); 里面的
bc2.Prinf();为什么输出的是虚方法呢?
SubClass2类里面的new不是隐藏了基类的方法吗?
1:还有我看书上说基类对象引用实例只能拥有自己的方法和属性(不能拥有派生类的方法或者属性)
2: 同理派生类对象实例化 就拥有了基类的属性和方法。
后面一句我到没有疑问 :前面一句 "1"(我看书上说基类对象引用实例只能拥有自己的方法和属性(不能拥有派生类的方法或者属性) 不是明显有问题吗?)如上面的例子
BaseClass bc1 = new SubClass1(); 申明一个基类 他的值bc1 并实例化subClass 对象赋值给bc1
这样bc1 不就拥有了 派生类的方法或者属性?
我将代码重新改了一下
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { BaseClass bc1 = new SubClass1(); BaseClass bc2 = new SubClass2(); SubClass1 sc1 = new SubClass1(); SubClass2 sc2 = new SubClass2(); bc1.Prinf(); bc2.Prinf(); sc1.Prinf(); sc2.Prinf(); } abstract public class BaseClass { public int i = 0; public virtual void Prinf() { Console.WriteLine("虚方法"); Console.WriteLine("i=" + i); } } class SubClass1 : BaseClass { public int j = 1; public override void Prinf() { Console.WriteLine("重写方法"); Console.WriteLine("j=" + j); } } class SubClass2 : BaseClass { public int k = 2; public new void Prinf() { Console.WriteLine("新方法"); Console.WriteLine("k=" + k); } } } }
可以运行一下上面的代码。看看结果。
现在来看看问题:
1:
BaseClass bc2 = new SubClass2(); 里面的
bc2.Prinf();为什么输出的是虚方法呢?
SubClass2类里面的new不是隐藏了基类的方法吗?
答:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。 隐藏继承的成员时,该成员的派生版本将替换基类版本。 虽然可以在不使用 new 修饰符的情况下隐藏成员,但会生成警告。 如果使用 new 显式隐藏成员,则会取消此警告,并记录要替换为派生版本这一事实。
对同一成员同时使用 new 和 override 是错误的做法,因为这两个修饰符的含义互斥。 new 修饰符会用同样的名称创建一个新成员并使原始成员变为隐藏的。 override 修饰符会扩展继承成员的实现。
也就是说SubClass2的new是隐藏基类的方法,但作为基类的对象bc2,是能够看到基类的方法的。
2:
还有我看书上说基类对象引用实例只能拥有自己的方法和属性(不能拥有派生类的方法或者属性)
同理派生类对象实例化 就拥有了基类的属性和方法。
答:面向对象的基本问题,老爸的东西(public的)都会留给儿子,而儿子的东西(public)并不是老爸的
BaseClass bc1 = new SubClass1() 这里也可以看到运行的结果是“重写方法 j=1”,看上去好像bc1拿到了儿子的东西,其实并不是这样,在vs里输入bc1. 然后可以看到弹出的方法或者属性是i和printf(),没有j。也就是说“基类对象引用实例只能拥有自己的方法和属性”。那么为什么显示的结果中确有j呢?这是因为bc1这个对象的类型是SubClass1,而它继承了BaseClass 并对printf进行了override操作。bc1因为printf被重写,所以显示了新的结果,但它自身的成员列表是不变的。
谢谢 朋友你这个解释很好!
老爸的东西(public的)都会留给儿子,而儿子的东西(public)并不是老爸的........ 我对着你的例子运行 bc1确实点不出j 看来书上说的确实没有错!
首先new这个关键字在此处的用法你还没太弄明白,override描述的方式在子类中把基类的方法内部实现用子类的实现替换掉,而new描述的方法则是子类中添加一个同名方法,也既是说在方法列表中有两个方法,一个是基类的,一个是子类的,子类在调用时默认调用子类实现的方法,而基类只能调用基类的方法。
不知道这么解释你明白不。
BaseClass bc1 = new SubClass1(); 申明一个基类 他的值bc1 并实例化subClass 对象赋值给bc1
这样bc1 不就拥有了 派生类的方法或者属性?
首先bc1指向的对象还是SubClass1类型的,只是bc1这个变量声明的类型是BaseClass,所以bc1的成员列表是BaseClass的。
谢谢朋友 明白了!
谢谢了朋友! 只能2选1 不好意思
@s_p: 没事,让你明白了就好。