今天讨论的接口、抽象类、抽象方法和虚方法都是以多为为基础的。
什么是多态?同一种操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。举一个形象的例子,在我们听音乐会的时候,当指挥发出开始的信号,不同的乐器收到相同的信号,但是他们产生不同的行为:钢琴发出的是钢琴的声音,小号发出的是小号的声响。或者,如果把每个动物当成一个对象,那么他们都有一个方法叫做吃,但是他们却产生不同的行为,猫吃鱼,狗吃骨头。
虚方法
首先来讨论虚方法。虚方法存在于相对于实现多态的子类的父类中,同时也是最基本的实现多态的方法。
C#中指出:普通方法的重载是指类中两个以上的方法取得名字相同,只要使用的参数类型或者参数个数不同,编译器就知道在哪种情况下调用哪个方法。而派生类中车重新定义虚方法的要求是:方法名称、返回值类型、参数列表中的参数个数、类型、顺序都必须和基类中的虚方法一样。
简单点说:子类中override的方法能够覆盖基类中的virtual方法,当把一个子类的实例转换成基类时,调用的方法还是子类的override方法。
一个类中两个名字一样的函数叫重载,基类和派生类中名字一样的函数叫重写,重写必须是用虚方法。
具体的语法是在基类中一virtual修饰,然后在子类中使用override重写。
例子:在父类中定义一个吃东西的方法,在子类中进行重写
/*定义父类Animal*/
public class Animal
{
public virtual void Eat()
{
Console.WriteLine("吃东西");
}
}
/*定义子类Dog,并重写方法Eat()*/
public class Dog
{
public override void Eat()
{
Consoel.WritrLine("狗狗吃骨头");
}
}
/*定义Cat类,并重写Eat()方法*/
public class Cat
{
public override void Eat()
{
base.Eat();//调用父类的Eat()方法
Console.WriteLine("猫咪吃小鱼"):
}
}
主程序
class Program
{
Cat cat = new Cat();
Dog dog = new Dog();
cat.Eat();
dog.Eat();
}
/*output:
吃东西
猫咪吃小鱼
狗狗吃骨头
*/
抽象方法和抽象类
通过上面的例子我们知道了虚方法。存在于父类中的虚方法是有方法体的,而且这些方法体是必要的,少了他们就无法完成逻辑。
如果父类中的方法完全不知道干什么,必须要子类进行重写才有意义的话,这种情况就需要使用抽象方法。
抽象方法必须存在于抽象类中,抽象类的具体语法是在类名前加上abstract。
抽象方法的语法示例:
public abstract void Fun();
抽象方法的语法示例:
public abstract class People{}
抽象方法是没有任何方法体的。
例子和上面的一样,父类有些变化。
abstract class Animal
{
public virtual void Eat();
}
子类的代码不变。但是不能使用base来调用父类的Eat()方法了,因为父类中的Eat()方法根本没有方法体。
抽象类中可以包含普通方法,并且抽象类不能被实例化。
抽象类的使用场景:
- 父类方法不知道如何去实现
- 父类没有默认实现且不需要实例化
总结:抽象方法和虚方法的差别并不是很大,实现的功能都差不多。抽象类保证了每个抽象方法都必须在子类中车重写,视情况来选择对应的方法。
接口
接口是从抽象类演变而来的——如果抽象类中的所有方法都是抽象方法,这个抽象类就可以叫做接口。当然,接口中的所有方法都不能有方法体。
接口中不能包含字段,但是可以包含属性。利用自动属性可以在接口中编写属性。
接口中的所有成员的访问级别都默认为public,这是不能被修改的,也不能自己写上去。
总结一些接口的特点:
- 通过接口可以实现多重继承,C#接口的成员不能有public、protected、internal、private等修饰符。原因是接口里面的方法都是需要由继承这个接口的类或者接口去实现,所以默认的访问级别就是public。C#中接口的成员默认是public
- 接口成员不能有new、static、abstract、override、virtual等修饰符。有一点注意,当一个接口实现一个接口,这两个接口中有相同的方法时,可以用new关键字隐藏父接口中的方法。
- 接口中只包含成员的签名,接口没有构造函数,所以不能直接使用new对接口进行实例化。接口中只能包含方法、属性、事件和索引的组合。接口一旦被实现,实现类必须实现接口中的所有成员。除非实现类本身是抽象类。
- C#是单继承,接口是解决C#里面类可以同时继承多个基类的问题。
例子:和上面一样,只是重新定义了一个接口
interface Interface1
{
void Dosth();//动物发出叫声
}
class Dog:Animal,Interface1
{
public override void Eat()
{
Consoel.WritrLine("狗狗吃骨头");
}
public void Dosth()
{
Console.WriteLine("汪");
}
}
class Cat:Animal,Interface1
{
public override void Eat()
{
Console.WriteLine("猫咪吃小鱼"):
}
public void Dosth()
{
Console.WriteLine("喵");
}
}
抽象方法和虚方的区别
- 抽象方法必须在抽象类中,虚方法可以存在于普通类中
- 抽象方法不能在基类中实现,只能在派生类中实现。虚方法可以在父类中实现,不实现也可以,但是要写出方法的签名并加上大括号,方法体为空就行
- 抽象方法在非抽象类中必须实现。虚方法可以选择实现或者不实现
- C#中属相也可以为虚属性
接口和抽象类的区别
- 抽象类中可以有实现的成员,而接口中的方法只有声明没有实现
- 抽象类中可以有字段,接口中不能有字段,可以有属性。
- 抽象类的成员可以使用公共或其他修饰符。接口中的成员你是默认公共的,不需要写修饰符。
- 抽象类是概念的抽象,接口是行为的规范的规定。
- 抽象类不支持多重继承,而一个类可以继承多个接口
以上就是本文讨论的内容,欢迎各位加以指正或者补充!谢谢!还有,以后写文章换个标题了,这个标题太长了……