base和this是c#中的两访问关键字,目的是用于实现继承机制的访问操作,来满足对对象成员的访问,从而为多态机制提供更加灵活的处理方式。
在看《你必须知道的.Net》一书中有一个例子很好的解释了base和this的用法。也很好的诠释了继承的概念,现附上书中代码:
class Action { public static void ToRun(Vehicle vehicle) { Console.WriteLine("{0} is running",vehicle.ToString()); } } public class Vehicle { private string name; private int speed; private string[] array = new string[10]; public Vehicle() { } public Vehicle(string name, int speed) { this.name = name; this.speed = speed; } public virtual void ShowResult() { Console.WriteLine("The top speed of{0} is {1}.",name,speed); } public void Run() { Action.ToRun(this); } public string this[int param] { get { return array[param]; } set { array[param] = value; } } } public class Car : Vehicle { public Car() : base("Car", 200) { } public Car(string name, int speed) : this() { } public override void ShowResult() { base.ShowResult(); Console.WriteLine("It's a car's result"); } } public class Audi : Car { public Audi() : base("Audi", 300) { } public Audi(string name,int speed) : this() { } public override void ShowResult() { base.ShowResult(); base.Run(); Console.WriteLine("It's audi's result."); } } class Program { static void Main(string[] args) { Audi audi = new Audi(); audi[1] = "A6"; audi[2] = "A8"; Console.WriteLine(audi[1]); audi.Run(); audi.ShowResult(); Console.Read(); } }
上边的代码,试着把子类Audi覆写的ShowResult()的override改为new,然后在客户端处理类里Vehicle ve = new Audi();ve.run();ve.ShowResult();
这样对于new隐藏继承成员和override覆写的层次顺序就会有更加清楚的概念。一方面了解了base作为和直接基类进行通信的方法以及this的基本用法,又复习了下通过基类继承来实现多态的方法。调用虚函数,进一步逐一判断是否在子类进行override覆写,若覆写就调用最后一个层次继承类的覆写方法,若没有则直接调用基类的虚方法。我想这大概也是这种多态的实现取决于运行时而非编译时的道理吧。
1.把new和Virtual总结一下:
实现派生类中隐藏方法,则基类方法必须定义为virtual,这主要是针对版本控制而言,将基类方法实现为virtual能够同时保证向前扩展和向后兼容,在派生类中通过new或override进行灵活控制;new作为修饰符,实现隐藏基类成员时,不可和override共存,但可以和virtual共存。new用于实现创建一个新成员,同时隐藏基类的同名成员;而override用于实现对基类成员的扩展。
2.base和this总结一下:
base常用于在派生类对象初始化时和基类进行通信。
base可以访问基类的公有成员和受保护成员,私有成员不可访问。
this指代类对象本身,用于访问本类的所有常量,字段,属性和方法成员,不管访问元素是任何访问级别。因为this仅仅局限于对象内部,对象外部无法看到,这就是this的基本思想。另外,静态成员不是对象的一部分,因此不能再静态方法中引用this。
在多层继承中,base可以指向父类的方法有两种:一是有覆写存在的存在的情况,base将指向直接继承的父类成员的方法;在没有覆写存在的情况下,base可以指向任何上级父类的公有或者受保护的方法。