C# 接口(interface)与抽象类(abstract)的区别
【虚方法】
virtual关键字用于在基类中修饰方法(或属性、索引器或事件声明),并且允许在派生类中重写这些对象(即override可写可不写)。
virtual的使用会有两种情况:
情况1:在基类中virtual方法在子类中没用override重写。那么在对子类实例的调用中,该虚方法使用的是基类定义的方法。
情况2:在基类中virtual方法在派生类中使用override重写。那么在对子类实例的调用中,该虚方法使用的是子类重写的方法。
【抽象方法】
abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现(没有方法体),抽象方法必须放在抽象类中(但抽象类中可以没有抽象方法)。
非抽象类的派生类必须全部实现父类的抽象方法和抽象访问器,使用override关键字来实现。
【接口】
接口用于描述一组类的公共方法/公共属性
接口中的方法没有具体实现,也就是没有方法体,必须由继承者去实现而且必须全部实现。
接口中的方法不需要修饰符,默认就是公有的(Default / Public)
接口可以包含方法、属性、索引器、事件。不能包含任何其他的成员,例如:常量、字段、域、构造函数、析构函数、静态成员
【虚方法 VS 抽象方法】
虚方法和抽象方法都可以供派生类重写
1. 虚方法必须有实现部分,抽象方法没有提供实现部分,抽象方法是一种强制派生类覆盖的方法,否则派生类将不能被实例化;而虚方法提供了选择,可以覆盖可以不覆盖。
2. 抽象方法只能在抽象类中声明,虚方法不是。
【抽象 VS 接口】
抽象类和接口都不能实例化(无法New创建实例,只能被继承)
抽象类可以包含非抽象方法,而接口只能包含抽象方法
一个类可以实现多接口,单继承。(可以继承多个接口,但只能继承单个类)
在学习c#接口(interface)和抽象类(abstract)的时候 发现接口和抽象类极为相似,比如说:继承后都需要重写,或者都不能通过new关键字来实例化… ,那么他们之间到底有什么区别与联系 ?
一、接口的特征
1、接口使用interface关键字声明
2、接口中的成员有属性、方法、事件,索引器并且都没有实现部分,可以说是没有方法体
3、接口中不能声明字段和常量,接口中的成员不能使用任何修饰符
4、继承接口的类或结构必须隐式或显式实现接口中的所有成员
5、一个接口允许继承多个接口,一个类也可以继承多个接口,但是只能继承一个基类。
C#不允许多重类继承(子类继承多个父类),但允许多重接口实现(子类继承多个父接口)。
6、接口不能通过new关键字来实例化
7、类或结构继承接口或不用使用override关键字即可实现
8、接口中没有实例构造函数
1 public interface IPict 2 { 3 void DisplayImage(); 4 } 5 6 public interface IPictManip 7 { 8 void DisplayImage(); 9 } 10 11 public class MyImages: IPict, IPictManip 12 { 13 void IPict.DisplayImage(){ //如果用显式接口实现方法,则不需使用访问修饰符 14 Console.WriteLine("DisplayImage的IPict实现"); 15 } 16 17 void IPictManip.DisplayImage() 18 { 19 Console.WriteLine("DisplayImage的IPictManip实现"); 20 } 21 22 23 static void Main(string[] args) 24 { 25 MyImages objM = new MyImages(); 26 IPict Pict = objM; //IPict引用 27 Pict.DisplayImage(); 28 29 IPictManip PictManip = objM; //IPictManip引用 30 PictManip.DisplayImage(); 31 }
二、抽象类的特征
1、抽象类中允许有实例方法,也就是说抽象类中除了抽象方法以外,其他的成员允许有具体的实现
2、抽象类中的抽象方法没有实现部分,也就是说没有方法体,并且继承此抽象类的非抽象类必须使用override关键字来重写抽象类中的所有方法
3、在抽象类中可以声明任何类成员,并且类成员可以使用任意的修饰符 (接口不行)
4、抽象类仅能让非抽象类和抽象类继承
5、非抽象类继承抽象类后必须重写(实现)抽象类中的所有抽象方法,抽象类继承抽象类后可以只实现部分抽象方法
三、总结
1、接口与抽象类的相同点
(1)都不能使用new关键字来实例化
(2)成员方法都没有实现部分,或者说都没有方法体
(3)继承他们的,都必须实现他们的成员方法
2、接口和抽象类的不同点
接口(interface) 抽象类(abstract)
接口中不能声明字段和常量,接口成员有:属性、方法、事件、索引器 抽象类中可以声明任何类成员
在接口中只能定义成员,但不能具体实现。(没有方法体) 在抽象类中除了抽象方法以外,其他成员允许有具体的实现
接口中没有实例构造函数,也就是说没有构造函数 抽象类中有构造函数
接口成员不能使用任何访问修饰符 抽象类中的类成员可以使用任意的访问修饰符
继承接口的类或结构必须隐式或显式实现接口中的所有成员,否则需要将实现类定义为抽象类,并将接口中未实现的成员以抽象的方式实现 继承抽象类的类必须重写实现抽象类中的所有抽象方法,或者抽象类继承抽象类,可以重写部分抽象方法
接口不能作为派生类继承 抽象类可以继承非抽象类或抽象类
接口可以作为基类来多继承:接口、类和结构 抽象类可以作为基类只能实现单继承,只能让非抽象类或者抽象类继承
抽象类(abstract)和接口(interface)的实现
抽象类
抽象方法是没有代码实现的方法,使用abstract关键字修饰;
抽象类是包含0到多个抽象方法的类,其不能实例化。含有抽象方法的类必须是抽象类,抽象类中也可以包含非抽象方法;
重写抽象类的方法用override关键字。
1 //定义一个抽象类,包含一个抽象方法,但该方法未实现 2 abstract class MyAbs 3 { 4 public abstract void AbMethod(); 5 } 6 7 //定义一个非抽象派生类,只能继承一个类 8 class MyClass:MyAbs 9 { 10 public override void AbMethod(){ 11 Console.WriteLine("此MyClass中实现父类中未实现的抽象方法!"); 12 } 13 14 //在主程序中实例化一个MyClass对象,并调用AbMethod方法 15 static void Main(string[] args) 16 { 17 MyClass objMyClass = new MyClass(); 18 objMyClass.AbMethod(); 19 }
虚方法(virtual)与抽象方法(abstract)的区别
虚方法必须要有方法体(方法体可以没有内容,但必须保留大括号),抽象方法不允许有方法体(不能有大括号);
父类的虚方法:
protected virtual void Initialization() { }
子类的方法重写:
protected override void Initialization() { MsgTypeName = NAME; LoadChildrenUIFormList = new List<string> { "TrainingGround_SkillInfoBoxUI" }; CurrentUIType.UIForms_ShowMode = UIFormShowMode.HideOther; }
2. 虚方法可以被子类重载(override)(也可以不重载,在对子类实例的调用中,该虚方法使用的是基类定义的方法),抽象方法必须被子类重载(必须重新继承实现);
3.虚方法除了在 (sealed) 密封类中都可以写,抽象方法只能在抽象类中写(抽象类中不是必须要有抽象方法,抽象方法可以为0个)。
接口
接口是一套规范,遵守这个规范就可以实现功能。
接口中只定义方法的原型,不能有字段和常量;
继承接口的类 必须实现接口中所有的方法 才能实例化
1 //隐式声明为public
2 public interface IPict{
3 //只有方法声明,没有访问修饰符,没有实现
4 int DeleteImage();
5 void DisplayImage();
6 }
定义派生自接口的类,并实现所有接口中的方法
1 public class MyImages: IPict{
2 //第一个方法的实现
3 public int DeleteImage(){
4 Console.WriteLine("DeleteImage实现!");
5 }
6
7 //第二个方法的实现
8 public void DisplayImage(){
9 Console.WriteLine("DisplayImage实现!");
10 }
11 }
在主程序中实例化一个MyImages对象,并调用DeleteImage和DisplayImage方法
1 static void Main(string[] args){
2 MyImages ofjM = new MyImages();
3 objM.DisplayImage();
4 int t = objM.DeleteImage();
5 Console.WriteLine(t);
6 }
多重接口实现
C#不允许多重类继承(子类继承多个父类),但允许多重接口实现(子类继承多个父接口)。但如果发生命名冲突就需要使用前缀进行显式接口实现或调用。如果继承接口的类中用显示方法实现接口中的方法时,实现方法不需加访问修饰符(public)
1 public interface IPict{
2 void DisplayImage();
3 }
4
5 public interface IPictManip{
6 void DisplayImage();
7 }
8
9 public class MyImages: IPict, IPictManip{
10 void IPict.DisplayImage(){ //如果用显式接口实现方法,则不需使用访问修饰符
11 Console.WriteLine("DisplayImage的IPict实现");
12 }
13 void IPictManip.DisplayImage(){
14 Console.WriteLine("DisplayImage的IPictManip实现");
15 }
16 }
17
18 static void Main(string[] args){
19 MyImages objM = new MyImages();
20 IPict Pict = objM; //IPict引用
21 Pict.DisplayImage();
22 IPictManip PictManip = objM; //IPictManip引用
23 PictManip.DisplayImage();
24 }
使用自定义接口
接口作为参数使用:接口作为参数传递了实现接口的对象
1 //无论谁收作业参数类型部分都不需做任何改变
2 private void DoCollectHomework(IHomeworkCollector collector){
3 collector.CollectHomework();
4 }
5
6 DoCollectHomework(scofield);
接口作为返回值使用:接口作为返回值返回了一个实现接口的对象
1 private IHomeworkColletor CreateHomeworkCollector(string type){
2 switch(type){
3 case "student":
4 collector = new Student("Scofield", Genders.Male, 28, "越狱");
5 break;
6 }
7 //返回一个实现该接口的对象
8 return collector
9 }
10
11 collector.CollectHomework();
————————————————
版权声明:本文为CSDN博主「Peter_Gao_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42672770/article/details/107730430
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章