.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)实现。
在实际应用中,子类仅能重写父类中的虚方法或者抽象方法,当不需要使用父类中方法的内容时,将其定义成抽象方法,否则将方法定义成虚方法。
抽象类
"一个包含一个或多个纯虚函数的类叫抽象类,抽象类不能被实例化,进一步
一个抽象类只能通过接口和作为其它类的基类使用."
一个抽象类可以包含抽象和非抽象方法,当一个类继承于抽象类,那么这个派生类必须实现所有的
的基类抽象方法。
但是通过声明派生类也为抽象,我们可以避免所有或特定的虚方法的实现,
这就是抽象类的部分实现。
看起来很高深?事实上抽象类就是一个提供了有部分没有方法体的函数和有具体实现的函数的集合。它相比于接口毫无实现而言,抽象类可以提供非抽象的方法,也就是说,抽象类中可以含有有实现方法的函数。
看这个例子
public abstract class A
{
public void GetSomeThing()
{
//todo
}
public abstract void SetSomeThing();
}
public class B:A
{
//实现抽象方法
public override void SetSomeThing()
{
//调用非抽象方法
base.GetSomeThing();
}
}
这里面涉及到了base关键字以及":"继承符号,在后面的继承、多态的课程有会有更加深入的介绍。
.NET Core CSharp初级篇 1-5 接口、枚举、抽象的更多相关文章
- NET Core CSharp初级篇 1-3面向对象
.NET Core CSharp初级篇 1-3 本节内容为面向对象初级教程 类 简介 面向对象是整个C#中最核心最有特色的一个模块了,它很好的诠释了程序与现实世界的联系. 面向对象的三大特征:继承.多 ...
- .NET Core CSharp初级篇 1-6 类的多态与继承
.NET Core CSharp初级篇 1-6 本节内容为类的多态与继承 简介 终于讲到了面向对象三大特性中的两大特性--继承与多态.通过继承与多态,我们能很好的将类的拓展性发挥到了极致.在下面的内容 ...
- .NET Core CSharp初级篇 类的生命历程
.NET Core CSharp初级篇 1-7 本节内容为类的生命周期 引言 对象究竟是一个什么东西?对于许多初学者而言,对象都是一个非常抽象的知识点.如果非要用一句话描述,我觉得"万物皆对 ...
- .NET Core CSharp初级篇 1-8泛型、逆变与协变
.NET Core CSharp初级篇 1-8 本节内容为泛型 为什么需要泛型 泛型是一个非常有趣的东西,他的出现对于减少代码复用率有了很大的帮助.比如说遇到两个模块的功能非常相似,只是一个是处理in ...
- .NET Core CSharp初级篇 1-2 循环与判断
.NET Core CSharp初级篇 1-2 本节内容循环与判断 循环 循环是一个在任何语言都是极为重要的语法,它可以用于很多东西,例如迭代数组等等.在C#中,语法层面的循环有:for , fore ...
- .NET Core CSharp初级篇 1-1
.NET Core CSharp初级篇 1-1 本节内容是对于C#基础类型的存储方式以及C#基础类型的理论介绍 基础数据类型介绍 例如以下这句话:"张三是一名程序员,今年15岁重50.3kg ...
- CSharp初级篇 1-4 this、索引器、静态、常量以及只读
.NET Core CSharp初级篇 1-4 本节内容为this.索引器.静态.常量以及只读 简介 在之前的课程中,我们谈论过了静态函数和字段的一小部分知识,本节内容中,我们将详细的讲解关于对象操作 ...
- .NET Core CSharp 中级篇 2-2 List,ArrayList和Dictionary
.NET Core CSharp 中级篇 2-2 本节内容为List,ArrayList,和Dictionary 简介 在此前的文章中我们学习了数组的使用,但是数组有一个很大的问题就是存储空间不足,我 ...
- .NET Core CSharp 中级篇 2-1 装箱与拆箱
.NET Core CSharp 中级篇 2-1 本节内容为装箱与拆箱 简介 装箱和拆箱是一个相对抽象的概念.你可以想象一下一堆满载货物的大卡车,他是由许多工人将货物集中堆放装入的,对于我们而言在没有 ...
随机推荐
- MacOS X编译OpenSceneGraph
本文主要记录在MacOS X上编译OpenSceneGraph,方便日后查阅.所使用的环境如下: MacOS X 10.10 Yosemite XCode 6.3.2 CMake 3.3.0 Open ...
- 基于Delphi实现客户端服务端通信Demo
在开始之前我们需要了解下这个Demo功能是啥 我们可以看到这是两个小project,左边的project有服务端和客户端1,右边的project只有一个客户端2 效果就是当两个客户端各自分别输入正确的 ...
- ThoughtWorks 面试备忘录
ThoughtWorks 面试备忘录 前言 前段时间 ThoughtWorks 在网上和拉勾网合作搞了一次网络招聘,名为抛弃简历!让代码说话!,可谓赚足了眼球,很多程序猿纷纷摩拳擦掌.踊跃提交代码,在 ...
- PNG透明窗体全攻略(控件不透明)
http://blog.csdn.net/riklin/article/details/4417247 看好了,这是XP系统,未装.net.我的Photoshop学的不太好,把玻璃片弄的太透了些,如果 ...
- Codility---PermCheck
Task description A non-empty zero-indexed array A consisting of N integers is given. A permutation i ...
- javaweb各种框架组合案例(一):maven+spring+springMVC+jdbcTemplate
为了体现spring jdbc对于单表操作的优势,我专门对dao层做了一个抽离,使得抽离出的核心dao具有通用性.主要技术难点是对于泛型的反射.注意:单表操作中,数据库表的字段要和实体类的属性名保持高 ...
- 3011C语言_基础知识
第一章 基础知识 1.1 基本框架 //任何一个c语言程序都必须包括以下格式: int main(int argc, char *argv[] ) { : } //这是c语言的基本结构,任何一个程 ...
- export命令的使用
一:export将环境变量昭告天下 1.直接输入export会将显示bash下的所有环境变量 2.env/set/export/declare都可以显示shell的变量 ...
- Tido c++树状数组知识讲解(转载)
树状数组可以用来动态计算前缀和,可以随时进行更新 而普通的前缀和只是静态的
- fork和僵尸进程
1. 关于fork fork()函数: 用于创建一个进程,所创建的进程复制父进程的代码段/数据段/BSS段/堆/栈等所有用户空间信息:在内核中操作系统重新为其申请了一个PCB,并使用父进程的PCB进行 ...