.NET Core CSharp初级篇 1-5 接口、枚举、抽象

.NET Core CSharp初级篇 1-5

本节内容类的接口、枚举、抽象

简介 问题

如果你需要表示星期或者是某些状态,使用字符串或者数字是否不直观?

你是否发现,无论何种电脑,它的USB口的设计都是遵循一定规范的?

枚举 枚举(enum)是一个非常好用的一个特殊值类型,他可以让你指定一系列字符常量(通常从0开始)。它的定义和使用如下:

public enum Week { Monday, ...//此处省略 Sunday = 6//可赋值 } bool flag = (6 == (int)Week.Sunday)

不过你也可以指定其他的类型作为枚举的值,例如:

public enum Week:byte { Monday, ... Sunday= 6 }

枚举与其他类型的转换使用强制类型转换即可,例如:(int)Week.Sunday,不过特别的,0不需要强制转换就可以和枚举进行比较。

Flag Enum

这是一个有趣的枚举,它支持你对枚举按位进行运算,使用flag enum需要在枚举名上面指定一个Attribute,也就是[Flags],通常来说,我们会使用2的幂作为枚举值,因为按位运算本质是2进制的运算。

具体实例如下

[Flags] public enum Status { Success = 1, NotFound = 2, Fail = 4 } //支持按位运算,运算步骤我们在之前已经有过详细的讲解 Status.Success | Status.NotFound

默认的,如果你输入了一个不合理的枚举值(也就是没定义),编译器会默认直接输出该数字,不过如果你使用了按位运算的枚举,那么他会将你输入的数字转换成二进制与每一个枚举值进行&运算,得出的结果会与枚举值进行比较,如果找到了就会输出。

例如以上例的Status:

Console.WriteLine((Status)7); //输出是三个都输出 //7 = 0111, //1 = 0001, //2 = 0010 //4 = 0011 接口

接口这个东西,新手非常容易被误导,例如在WebApi开发中,你的前端朋友让你把接口给他,这个时候,他需要的东西在后端的口中叫做API,
当你的后端朋友说,你写一个接口,我们使用依赖注入进行统一管理实现了接口的类,这个时候,他需要的是一个约定,也是我们这里讲的接口(interface)。

接口是C#面向对象中实现多态的重要语法。接口的定义可以理解为是一种约定的规范。例如电脑的USB-A接口,全世界的厂商都是统一规范生产,如果大家不按着约定生产,后果会是什么?

C#中,接口也一样起到了这个作用,但是还有一些更为广泛的应用。

接口的定义使用interface关键字,默认的,所有接口的成员的访问权限都是public,因为规范是需要公布给所有人看,如果定义了访问权限就没有实际的意义了
,并且接口中所有的函数都不存在函数体。总的来说就是,接口是一个提供类的规格的东西,却不提供实现。

接口的例子

//定义一个接口 public inteface IHuman { void Eat(); bool Alive(); } //接口的实现,必须实现每一个接口中的函数并保持返回类型、函数签名,函数参数一致 public class Human:IHuman { void Eat() { } bool Alive() { return default<bool>(); } }

接口的实现会和我们后面讲到的继承非常相似,在这里,你只需要记住接口支持一个类实现多个接口,但只能继承一个类即可。

接口冲突

因为支持一个类实现多个接口,那么很有可能会造成A接口中拥有和B接口中完全一致的函数,这个时候我们就需要使用显式实现接口进行处理。

当你需要调用不同接口的同签名方法时,使用接口进行强制转换即可。

例如:

interface IApple { void Wash(); } interface IFruit { void Wash(); } class test : IApple,IFruit { void IApple.Wash()=>{}; void IFruit.Wash()=>{}; } test t= new test(); ((IApple)t).Wash(); ((IFruit)t).Wash();

这样就可以避免接口在命名上的冲突。

并且接口如果你隐式的实现,所有接口函数默认都是sealed的。
如果存在一个多继承的问题,这个可能目前讲起来为之过早,我就顺口提一下,例如,人类继承与动物类,动物继承于生物接口,
那么对于人类,是隐式的继承了生物接口,但是对于人类和动物,进食的方式有很大区别,那么我们就应该重写进食这个方法。
我们就要把基类(父类)中的接口函数标记为virtual或者abstract,然后在子类中使用override进行重写。

这就已经说的太远了,后面我们会进行深入的刨析。

抽象

抽象可以有抽象字段、抽象类、抽象委托、抽象函数等等。我们就以其中常用的抽象函数和抽象类做一个解析。

抽象和接口非常相似,抽象类不能被实例化,抽象方法没有方法体,都是依赖子类(被继承类)进行操作。

抽象函数

这个就和接口几乎一模一样,也没有太多讲的必要,如果你声明了一个函数是抽象函数,那么它不存在方法体,你需要通过子类去重写(override)实现。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxpxz.html