C#里氏转化原则、抽象类、接口
C#中可以使用一个父类类型的变量来引用一个子类类型的对象,即将子类对象当作父类类型使用,这就是所谓的里氏转化原则
1.子类对象可以直接赋值给父类变量。并且通过父类变量可以调用子类中的方法,这个子类的方法要是对父类的方法进行重写的方法,于父类无关系的方法不能被调用
namespace 里氏转化
class Program
static void Main(string[] args)
Animal an1 = new Dog();//里氏转化,父类类型的变量来引用一个子类类型的对象
an1.Shout();//父类的变量调用子类的方法,此方法是对父类的方法进行了重写,其他无关系的方法将不能被调用
Console.ReadKey();
class Animal
public virtual void Shout()//虚方法
Console.WriteLine("动物在叫");
class Dog : Animal
public override void Shout()//对父类的方法进行了重写,从而实例化的时候,父类类型的变量可以直接调用子类对象的方法
Console.WriteLine("狗在叫");
2.将父类变量转换为子类类型
要想将父类变量转换为子类类型,只能在一种特殊情况下实现,即父类变量引用的是当前子类对象
namespace 里氏转化父类转子类
class Program
static void Main(string[] args)
Animal an1 = new Dog();
an1.Shout();
Dog dog = (Dog)an1;//父类对象an1强转为子类类型
dog.Shout();
dog.Run();
class Animal
public void Shout()
Console.WriteLine("叫");
class Dog : Animal
public void Run()
Console.WriteLine("跑");
在继承关系中当子类对象赋值给父类变量的情况下,父类变量可以通过强转指向子类变量。但是如果不知道他们是否是继承关系的情况下,强转类型就可能出现未知错误。所以可以使用c#提供的is和as关键字。
is和as都是可以用来判断父类变量是否指向子类,as关键字除了判断之外,还有直接转换的功能。如果判断成功就直接进行类型转换,如果判断失败就返回null。
namespace is和as的关键字
class Program
static void Main(string[] args)
Animal an1 = new Dog();//下面的is语句和as语句使用的前提必须要有这句话,否则都是报错
bool result = an1 is Dog;//申请一个bool类型的变量去判断an是否指向dog类型
if (result)//判断结果
Console.WriteLine("an1能转换Dog类型");
Console.WriteLine("an1不能转换Dog类型");
Dog dog = an1 as Dog;//as语句除了判断还可以直接转换
if (dog != null)
Console.WriteLine("可以转换,已经转换成功");
Console.WriteLine("转换失败");
Console.ReadKey();
class Animal
public void Shout()
Console.WriteLine("jiao");
class Dog:Animal
public void Run()
Console.WriteLine("pao");
抽象类
当定义一个类是,常常需要定义一些方法来描述该类的行为特征,但有时这些方法的实现方法是无法确定的
例如在前面定义Animal类时,Shout()方法用于表示动物的叫声,但是针对不同的动物,叫声也是不同的,因此在Shout()方法中无法准确描述动物的叫声。就像这种情况,C#允许在定义方法时不写方法体,不包含方法体的方法为抽象方法,抽象方法必须使用asbstract关键字来修饰,例如abstract void Shout();//定义首相方法Shout()
当一个类中包含了抽象方法,该类必须使用abstract关键字来修饰,使用abstract关键字修饰的类为抽象类。
在定义抽象类的时候需要注意,包含抽象方法的类必须声明为抽象类,但抽象类可以不包含抽象方法,另外,抽象类是不可以被实例化的,因为抽象类中有可能包含抽象方法, 抽象方法是没有方法体的,不可以被调用,如果想调用抽象类中定义的方法,则需要创建一个子类,在子类中实现抽象类的抽象方法。
在调用时,必须要把抽象类的抽象方法都实现,否则就会直接报错。在子类中实现抽象类的方法时,要用重写的方式,关键字为override
namespace 抽象类
class Program
static void Main(string[] args)
Dog dog = new Dog();//实例化,因为抽象类是不能被实例化的,我们在子类中已经增加了抽象方法的具体方法体,所以我们直接实例化子类就可以了
dog.Run();//调用方法
dog.Shout();
Console.ReadKey();
abstract class Animal//定义一个抽象类
public abstract void Shout();//定义一个抽象方法,抽象方法是不包含方法体的
public abstract void Run();//定义一个抽象方法
class Dog : Animal//定义一个类,继承这个抽象类,在这个子类中实现抽象类中的所有抽象方法,否则就会报错
public override void Run()//重写这个方法,实现这个抽象方法的具体功能,增加方法体
Console.WriteLine("pao");
public override void Shout()//重写这个方法,实现这个抽象方法的具体功能,增加方法体
Console.WriteLine("jiao");
接口
接口的关键字是interface,如果一个抽象类中的所有方法都是抽象的,则可以将这个类用另外一种方式来定义,即接口。在定义接口时,需要使用interface关键字来声明。
定义方法
interface Animal
{
void Breathe();//定义抽象方法
void Run();//定义抽象方法
}
因为接口中定义的方法和变量都包含一些默认修饰符public,且不能显示添加修饰符。另外,接口中的抽象方法不需要用asbstract关键字修饰(而抽象类中的抽象方法必须要用asbstract修饰,且子类实现抽象方法时用override关键字重写抽象方法)
由于接口中的方法都是抽象方法。因此不能通过实例化对象的方法来调用接口中的方法,此时需要定义一个类,并实现就扣的所有方法
接口特点:
1.接口中的所有方法都是抽象的,因此接口不能被实例化
2.一个类可以是实现多个接口,被实现的多个接口之前用逗号分隔
3.一个接口可以继承多个接口,接口之前用逗号分隔(一个类不可以继承多个类,只能有一个直接父类)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 接口
class Program
static void Main(string[] args)
Dog dog = new Dog();
dog.Run();
dog.Shout();
Cat cat = new Cat();
cat.Jump();
cat.Run();
cat.Shout();
Fish fish = new Fish();
fish.Jump();
fish.Run();
fish.Shout();
fish.Swim();
Console.ReadKey();
interface Animal//定义一个接口
void Shout();
void Run();
interface LandAnimal//定义一个接口
void Jump();
interface MarineAnimal:Animal,LandAnimal//一个接口可以继承多个接口
void Swim();
class Dog : Animal//类与接口的关系
public void Shout()
Console.WriteLine("我是狗,我会叫");
public void Run()
Console.WriteLine("我是狗,我会跑");
class Cat : Animal,LandAnimal//一个类可以实现多一个接口
public void Shout()
Console.WriteLine("我是猫,我会叫");
public void Run()
Console.WriteLine("我是猫,我会跑");
public void Jump()
Console.WriteLine("我是猫,我会跳");
class Fish: MarineAnimal//实现这个接口,但是这个接口继承了多个接口,如果要实现这个接口,需要把它继承的接口的方法都实现
public void Shout()
Console.WriteLine("我是鱼,我会叫");
public void Run()
Console.WriteLine("我是鱼,我会跑");
public void Jump()
Console.WriteLine("我是鱼,我会跳");
public void Swim()