谈谈C#的继承机制(“子承父业”)
我们经常谈到面向对象的重要特性之一:继承,需要理解继承的重要机制:
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可在同一应用程序集中的类访问。