概念
在派生类中重写基类方法
规则
- 派生类的方法和基类的方法有相同的签名和返回类型。
- 基类的方法使用virtual标注。
- 派生类的方法使用override标注。
例
class MyBaseClass
{
virtual public void Print() //基类
{
Console.WriteLine("基类");
}
}
class MyDerivedClass:MyBaseClass //派生类
{
override public void Print()
{
Console.WriteLine("派生类");
}
}
class Program
{
static void Main(string[] args)
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass mybc = (MyBaseClass)derived; //转换成基类
derived.Print(); //从派生类部分调用Print
mybc.Print(); //从基类部分调用Print
Console.ReadKey();
}
}
结果
派生类
派生类
分析
当使用基类引用(mybc)调用Print方法时,方法调用被传递到派生类并执行,因为:
- 基类的方法被标记为virtual;
- 在派生类中有匹配的override方法。
注意
- 覆写和被覆写的方法必须有相同的可访问性。换一种说法,被覆写的方法不能是private等,而覆写方法是public。
- 不能覆写static方法或非虚方法。
- 方法、属性和索引器,以及另一种成员类型事件,都可以被声明为virtual和override。
覆写标记为override的方法
override可以为另一个override方法进行重写
规则
- 当使用对象基类部分的引用调用一个覆写的方法时,方法的调用被沿派生层次上溯执行,一直到标记为override的方法的最高派生版本。
- 如果在更高的派生级别有该方法的其他声明,但没有被标记为override,那么它们不会被调用。
1.使用override声明Print
class MyBaseClass
{
virtual public void Print()
{
Console.WriteLine("基类");
}
}
class MyDerivedClass:MyBaseClass
{
override public void Print()
{
Console.WriteLine("派生类");
}
}
class SecondDerived:MyDerivedClass //最高派生类
{
public override void Print()
{
Console.WriteLine("派生类2");
}
}
class Program
{
static void Main(string[] args)
{
SecondDerived derived = new SecondDerived();
MyBaseClass mybc = (MyBaseClass)derived; //转换成基类
derived.Print(); //从派生类部分调用Print
mybc.Print(); //从基类部分调用Print
Console.ReadKey();
}
}
结果
派生类2
派生类2
分析
SecondDerived的Print方法声明为override,那么它会覆盖方法全部两个低级派生类别版本
如果一个基类的引用被用于调用Print,它会向上传递通过整个链达到类SecondDerived中实现
两条语句中的第一条使用最高派生类SecondDerived的引用调用Print方法。这不是通过基类部分的引用的调用,所以它将会调用SecondDerived中实现的方法。
而第二条语句使用基类MyBaseClass的引用调用Print方法。
2.使用new声明Print
class SecondDerived:MyDerivedClass //最高派生类
{
public new void Print()
{
Console.WriteLine("派生类2");
}
}
class Program
{
static void Main(string[] args)
{
SecondDerived derived = new SecondDerived();
MyBaseClass mybc = (MyBaseClass)derived; //转换成基类
derived.Print(); //从派生类部分调用Print
mybc.Print(); //从基类部分调用Print
Console.ReadKey();
}
}
结果
派生类2
派生类
分析
当方法Print通过SecondDerived的引用调用时,SecondDerived中的方法被执行
当方法通过NyBaseClass的引用调用时,方法调用只向上传递了一级,到达类MyDerived,在那里它被执行。
覆盖其他成员
class MyBaseClass
{
private int _myInt = 5;
virtual public int MyProperty
{
get
{
return _myInt;
}
}
}
class MyDerivedClass:MyBaseClass
{
private int _myInt = 10;
override public int MyProperty
{
get
{
return _myInt;
}
}
}
class Program
{
static void Main(string[] args)
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass mybc = (MyBaseClass)derived; //转换成基类
Console.WriteLine($"derived.MyProperty:{derived.MyProperty}");
Console.WriteLine($"mybc.MyProperty:{mybc.MyProperty}");
Console.ReadKey();
}
}
结果
derived.MyProperty:10
mybc.MyProperty:10
不推荐在构造函数中调用虚方法