PS:注释和讲解全在代码中
- 虚方法等同于虚函数
- 抽象方法等同于纯虚函数
1. 虚函数与里氏转换原则
虚方法使用细节:
- 将父类的方法标记为虚方法,就是在父类方法的返回值前加virtual关键字,表示这个方法可以被子类重写
- 子类重写父类方法:在子类的方法的返回值前加override关键字,当然子类也可以不重写,或者是用new隐藏
- 父类中用virtual修饰的方法,可以在子类重写该的方法中,使用base关键字先调用父类中的该方法
里氏转换原则:
- 子类对象可以直接赋值给父类变量
- 子类对象可以调用父类中的成员,但是父类对象永远只能调用自己的成员
- 如果父类对象中装的是子类对象,可以将这个父类对象强转为子类对象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C4_程序设计
{
class Father
{
public virtual void Print() //虚函数当然不能是私有的
{
Console.WriteLine("Father!");
}
}
class SonA: Father
{
public override void Print()
{
//base.Print(); //可以用base.访问父类的函数/变量
Console.WriteLine("SonA!");
}
}
class SonB: Father
{
public new void Print()
{
Console.WriteLine("SonB!");
}
}
class GrandsonA: SonA
{
public override void Print()
{
Console.WriteLine("Grandson!");
}
}
class GrandsonB: SonA
{
public new void Print()
{
Console.WriteLine("Grandson!");
}
}
class 虚函数与里氏转换原则
{
static void Main()
{
Father fa = new Father();
Father me = new SonA(); //me的申明类是Father,实例类是SonA
Father you = new SonB();
fa.Print(); //Father!
me.Print(); //SonA! //体现了多态性
you.Print(); //Father! //申明类不是SonB,所以SonB的new Print()当然不会起效,这也是new(隐藏)和override(重写)的区别
me = new GrandsonA();
me.Print(); //Grandson!
you = new GrandsonB();
you.Print(); //SonA!
//you.Print流程如下:先检测申明类Father → 检测到虚函数 → 转去检查实例类GrandsonB,发现并没有override重写
//→再转去检查它的父类,也就是SonA,找到override,执行函数输出SonA!
GrandsonB text = (GrandsonB)you; //里氏转换原则③
text.Print(); //Grandson!
//is关键字:判断当前变量是否可以是当前类的对象,也就是是否可以强制转换成功,返回bool
Console.WriteLine(you is GrandsonB); //True
Console.WriteLine(you is Father); //True
Console.WriteLine(you is GrandsonA); //False
//as关键字:判断当前变量是否可以是当前类的对象,也就是是否可以强制转换成功,成功返回对应对象,失败返回null
fa.Print(); //Father!
fa = you as GrandsonB;
fa.Print(); //SonA!
}
}
}
2. 抽象类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C4_程序设计
{
//抽象类中不一定要有抽象方法,但是抽象方法必须存在于抽象类中
abstract class Base //在定义类的关键字class前面加abstract修饰的类就是抽象类,抽象类不可以实例化
{
public abstract void Dis(); //抽象方法
public virtual void Dis2()
{
Console.WriteLine("虚函数");
}
public void Dis3()
{
Console.WriteLine("普通函数");
}
}
class Text: Base
{
public override void Dis() //子类继承抽象类,必须使用override关键字重写父类中所有的抽象方法
{
Console.WriteLine("纯虚函数");
}
public override void Dis2()
{
Console.WriteLine("虚函数->子类");
}
public new void Dis3()
{
Console.WriteLine("普通函数->子类");
}
}
class 抽象类
{
static void Main()
{
Base me = new Text();
me.Dis();
me.Dis2();
me.Dis3();
}
}
}
/*
纯虚函数
虚函数->子类
普通函数
*/