我们经常谈到面向对象的重要特性之一:继承,需要理解继承的重要机制:
1. 可传递性。C-->B,B-->A ==> C-->A,即C继承A中所有非私有成员。
2. 对基类进行扩展。即派生类在拥有基类成员的同时可添加新的成员,但不能移除已继承的成员。
3. 对基类的构造函数和析构函数不能继承。则实例化派生类对象时,将先执行基类的构造函数,再执行自身的构造函数。
析构函数正好相反。
class Parent { public Parent() { Console.WriteLine("Parent Construtor"); } ~Parent()//不建议定义,因为.NET有GC机制 { Console.WriteLine("Parent Deconstrutor"); } public void Say() { Console.WriteLine("I'm Parent"); } } class Child : Parent { public Child() { Console.WriteLine("Child Construtor"); } ~Child() { Console.WriteLine("Child Deconstrutor"); } public void SayHello() { base.Say();//通过base访问 } } //以如下方式调用: Child c = new Child(); c.Say(); c.SayHello();//通过base.成员名访问 ((Parent)c).Say();//通过显式转化 /* Parent Construtor * Child Construtor * I'm Parent * I'm Parent * I'm Parent * Child Deconstrutor * Parent Deconstrutor */
4. 可覆盖(new)已继承的基类(接口不支持)同名成员,使之在派生类中隐藏。但并不会删除该同名成员,能通过base.成员名访问。
5. 可重写(override)在基类(可为抽象类)中定义的虚成员(virtual),从而表现出面向对象另一特性:多态性。
class Parent { public void Say() { Console.WriteLine("I'm Parent"); } public virtual void SayHello() { Console.WriteLine("Hello: Parent"); } } class Child : Parent { public new void Say() { Console.WriteLine("I'm Child"); } public override void SayHello() { Console.WriteLine("Hello: Child"); } } //以如下方式调用: Child c1 = new Child(); c1.Say();//I'm Child c1.SayHello();//Hello: Child Parent c2 = new Child(); c2.Say();//I'm Parent c2.SayHello();//Hello: Child
new与override的区别:new是编译时多态(根据对象定义时确定类型并调用相应类的方法),override是运行时多态(根据对象分配内存时确定类型并调用相应的方法)。
6. 只能从一个基类继承,可以通过实现多接口来模拟多重继承。注意:如果实现的接口不止一个且接口之间包含同名成员时,
则实现接口时不能用任何访问修饰符(public也不行),只能通过接口名.成员名来实现。对其他非同名成员实现时必须加public。
interface ITestA { void Say(); void TestA(); } interface ITestB { void Say(); void TestB(); } class Test : ITestA, ITestB { //实现ITestA void ITestA.Say() { Console.WriteLine("I'm ITestA"); } public void TestA() { Console.WriteLine("TestA"); } //实现ITestB void ITestB.Say() { Console.WriteLine("I'm ITestB"); } public void TestB() { Console.WriteLine("TestB"); } } //以如下方式调用: Test t = new Test(); ((ITestA)t).Say();//I'm ITestA ((ITestB)t).Say();//I'm ITestB t.TestA();//TestA t.TestB();//TestB
注:对继承的类之间,public, protected(internal)可以在基类与派生类中之间访问。而private仅能当前的类(以及内部类)中访问。internal可在同一应用程序集中的类访问。