在研究重写和覆盖之前我们先来研究下继承关系中构造函数和方法的执行顺序问题。
继承关系中的构造函数和方法执行顺序:
class A
{
public A()
{
Console.WriteLine("这是a构造函数");
}
public void a()
{
Console.WriteLine("这是a方法");
}
}
class B : A
{
public B()
{
Console.WriteLine("这是b构造函数");
}
public void b()
{
Console.WriteLine("这是b方法");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("创建父级===============================================");
A a = new A();
Console.WriteLine("创建子级===============================================");
B b = new B();
Console.WriteLine("父级开始调用a方法======================================");
a.a();
Console.WriteLine("子级开始调用b方法======================================");
b.b();
Console.WriteLine("创建一个像父级的子级===================================");
A a1 = new B();
a1.a();
Console.Read();
}
}
创建父级===============================================
这是a构造函数
创建子级===============================================
这是a构造函数
这是b构造函数
父级开始调用a方法======================================
这是a方法
子级开始调用b方法======================================
这是b方法
创建一个像父级的子级===================================
这是a构造函数
这是b构造函数
这是a方法
笔记:
1.创建子级的时候先执行父级构造函数再执行子级构造函数
2.申明一个父级可以创建子级的实例,反过来申明一个子级不能创建一个父级实例(儿子长得像父亲,但是父亲长得像儿子。。有点怪怪的,哈哈哈)
子级父级调用相同的方法:
class A
{
public void a()
{
Console.WriteLine("这是父级a方法");
}
}
class B : A
{
public void a()
{
Console.WriteLine("这是子级a方法");
}
}
class Program
{
static void Main(string[] args)
{
A a = new B();
a.a();
}
}
这是父级a方法
笔记:
1.子级和父级方法同名,子级方法覆盖父级方法
2.系统会提出警告
如何消除警告?
毕竟我们要达到“0 error,0 warning”,这里我们只需要在子级方法里面加上new关键字即可消除警告,new关键字在这里的作用就是覆盖父级同方法名,结果不变
class B : A
{
public new void a()
{
Console.WriteLine("这是子级a方法");
}
}
那么有些时候,我父级的一个方法就是为了给子类扩展自己这个方法的特别之处,比如鸟类有翅膀,子类的燕子既有翅膀还飞得贼快,子类鸵鸟虽然有翅膀但它不能飞。别人就说所有的鸟都能飞,那么我给一个鸵鸟给他是不是证明了他说的是错误的。
只要能用到父级的地方,我们都能够用他的子类来代替,因为子类包括父类的特征,这个就是我们面向对象原则里面的里氏代换原则。有些时候父级的一些方法不能实现我们想要的效果,那么我们就重写这个父类的这个方法。
重写
重写父级的方法用关键字virtual标记父级的方法,表示这个方法是一个虚方法,在子级用override重写父级标记的方法,这两个关键字是一起使用的。如果父级virtual标记了但是子级没有使用override重写,那是没有效果的,下面看代码:
class A
{
public virtual void a()
{
Console.WriteLine("这是父级a方法");
}
}
class B : A
{
public override void a()
{
Console.WriteLine("这是重写父级a方法");
}
}
class Program
{
static void Main(string[] args)
{
A a = new B();
a.a();
}
}
这是重写父级a方法