当一个类A派生出新类B时,这个基类A在新类B中可以表现为不同的类型:用作它自己的类型、基类型,或者在实现接口时用作接口类型,我们将这种情况称为多态性。
C#中的每种类型都是多态性的,都可以用作它们自己的类型或者用作Object实例,因为所有的类型都自动将Object当做基类型。
基类的设计者可以预测到其基类中可能会在派生类中发生更改的方面。比如,表示汽车的基类可能包含这样的行为:当考虑的汽车为小型货车或敞蓬汽车时,这些行为将会改变。基类可以将这些类成员标记为虚拟的,从而允许表示小型货车和敞蓬汽车的派生类重写该行为。
当派生类从基类继承时,它会获得基类的所有方法、字段、属性和事件。
提示:当派生类成员所需要的数据类型和行为与基类中同名成员的数据类型和行为不一致时,我们就需要在派生类中修改基类中同名成员的数据类型和行为了。前面文章中讲的继承都是指同名成员的数据类型和行为完全一致的情况下的继承,在这里讲的是不一致的情况下的继承的方法。
要更改基类的数据和行为,有两种选择:可以使用新的派生成员替换基类的成员,或者可以重写虚拟的基类成员。
一、使用新的派生成员替换基类的成员
使用new关键字可以让新的派生成员替换基类中的同名成员。如果基类中定义了一个方法、字段或属性,则可以使用new关键字在派生类中创建该方法、字段或属性的新定义。
例如,在基类中定义一个方法、字段或属性:
public class A
{
public void Method(){ }
public int Field;
public int Property;
{
get{return 0;}
}
}
下面在派生类中创建该方法、字段或属性的新定义:
public class B : A
{
public new void Method(){ }
public new int Field;
public new int Property;
{
get{return 0;}
}
}
使用new关键字时,调用的是新的类成员而不是已被替换的基类成员。这些基类成员称为隐藏成员。
如果将派生类的实例强制转换为基类的实例,就仍然可以调用隐藏类成员。
例如:
B b = new B();
b.Method(); // 调用派生类中的新方法
A a = (A)b; // 将派生类B的实例b强制转换为基类A的实例a
a.Method(); // 调用基类中的旧方法二、重写虚拟的基类成员
1. 使用virtual关键字重写虚拟的基类成员
使用virtual关键字可以将基类中的成员声明为虚拟的,以便让派生类的实例完全接替来自基类的该类成员。然后,派生类可以使用override关键字将基类实现替换为它自己的实现。
例如,将基类中的成员声明为虚拟的:
public class A
{
public virtual void Method(){ }
public virtual int Property;
{
get{return 0;}
}
}在派生类中替换为它自己的实现:
public class B : A
{
public override void Method(){ }
public override int Property;
{
get{return 0;}
}
}
2. 示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
class Program
{
public class A
{
public virtual void AAA()
{
Console.WriteLine("基类A");
}
}
class B : A
{
public override void AAA()
{
Console.WriteLine("派生类B");
base.AAA();
}
}
class C : A
{
public override void AAA()
{
Console.WriteLine("派生类C");
base.AAA();
}
}
class D : A
{
public override void AAA()
{
Console.WriteLine("派生类D");
base.AAA();
}
}
static void Main(string[] args)
{
// C#重写虚拟的基类成员-www.baike369.com
System.Collections.Generic.List<A> a =
new System.Collections.Generic.List<A>();
a.Add(new B());
a.Add(new C());
a.Add(new D());
foreach (A i in a)
{i.AAA();}
Console.WriteLine("请按任意键退出!");
Console.ReadKey();
}
}
}
运行结果:
派生类B
基类A
派生类C
基类A
派生类D
基类A
请按任意键退出!在基类中可以定义并实现虚方法,派生类可以重写这些方法,就是指派生类可以提供自己的定义和实现。