C#笔记(Virtual,Abstract,Override,new)

C#笔记(Virtual,Abstract,Override,new)

1.Virtual + Override

C#支持重写实例方法和属性,但不支持重写字段或任何静态成员。

为了进行重写,要求在基类和派生类中都显式地执行一个操作,在基类中,必须将允许重写的每个成员标记为virtual。假如一个virtual或protected成员没有包括virtual修饰符,就不允许子类重写该成员。

与Java相比,默认情况下Java中的方法都是虚方法,如果希望方法具有非虚的行为,就必须显示密封它。相反,C#的方法都默认为非虚方法,想要子类重写它就必须用virtual修饰符修饰。

另外,override修饰符在这时候必须要和virtual配套使用。与Java和C++不同,C#应用于派生类的override关键字是必须的。C#不允许隐式重写。为了重写方法,基类和派生类成员必须匹配,而且要有对应的virtual和override关键字。此外,override关键字意味着派生类的实现会替换基类的实现。

//重写属性
public class Father
  public virtual string Name{ get; set; }
  //...
public class Son : Father
  public override string Name
    get{ //...}
    set{ //...}

2.new修饰符

如果父类方法用了virtual修饰符,子类重写方法没有override关键字,编译器就会报错。

这里一个明显的解决方案是为子类方法添加override修饰符(假如它的父类成员是virtual的),但是第二种方法是使用new修饰符,这种情况称为脆弱的基类。

new修饰符在基类面前隐藏了派生类重新声明的成员,这时不是调用派生的最远的成员。相反,是搜索继承链,找到使用new修饰符的那个成员之前的成员,然后调用该成员。

举例来说,有一个基类Father,它有子类Son和孙子类GrandSon。

public class Program
  public class Father
    public virtual void func()
      Console.WriteLine("Father"); 
  public class Son : Father
    public override void func()
      Console.WriteLine("Son");
  public class GrandSon : Son
    public new void func()
      Console.WriteLine("GrandSon");
  public static void Main()
    GrandSon grandSon = new GrandSon();
    Son son = grandSon;
    Father father = grandSon;