面向对象编程进阶


1.类的继承与多态
继承是面向对象编程最重要的特性之一。任何类都可以从另外一个类继承,这就是说,这个类拥有它继承的类的所有成员。在面向对象编程中,被继承的类称为父类或基类。C#中提供了类的继承机制,但只支持单继承,而不支持多重继承,即在C#中一次只允许继承一个类,不能同时继承多个类。 
bass关键字用于从派生类中访问基类的成员它主要有两种使用形式:
调用基类上已被其他方法重写的方法
指定创建派生类实例时应调用的基类构造函数。
继承中的构造函数与析构函数
子类对象在创建时首先会调用父类的构造函数,在父类的构造函数执行结束后,再执行子类的构造函数。当父类的构造函数有参数时,需要在子类的初始化列表中显示调用。
析构函数的调用的先后顺序与构造函数相反
结论:构造函数:先调用父类 再调用子类 析构函数:先调用子类 再调用父类 
多态
虚方法的重写
在类的方法前面加上关键字virtual,则称该方法为虚方法。通过对虚方法重写,可以实现在程序运行过这个对象调用派生类的方法。
多态使子类(派生类)的实例可以直接赋予基类的变量(这里不需要进行强制类型转换),然后直接就可以通过这个变量调用子类(派生类)的方法。  在派生于同一个类的不同对象上执行任务时,多态是一种极为有效的技巧,使用的代码最少。可以把一组对象放到一个数组中然后调用它们的方法,在这种情况下多态的作用就体现出来了,这些对象不必是相同类型的对象。当然如果它们都继承自某个类,可以把这些子类(派生类)都放到一个数组中。如果这些对象都有同名方法,就可以调用每个对象的同名方法。
如果一个类不与具体的事物相联系,而只是表达一种抽象的概念,仅仅是作为其派生类的一个基类,这样的类就是抽象类。在抽象类中声明方法时,如果加上abstract关键字,则为抽象方法 
抽象类主要用来提供多个派生类可共享的基类的公共定义,它与非抽象类的主要区别如下。
①抽象类不能直接实例化。
②抽象类中可以包含抽象成员,但非抽象类中不可以。
③抽象类不能被密封。
C#中声明抽象类时需要使用abstract关键字,
抽象方法就是在声明方法时,加上abstract 关键字,声明抽象方法时需要注意以下两点。
①抽象方法必须声明在抽象类中。
②声明抽象方法时,不能使用 virtual、static 和 private 修饰符。
密封类和密封方法
有些时候,我们并不希望所编写的类被继承,如果所有的类都可以被继承,则类的层次结构将会变得十分复杂,从而加重理解类的困难。此时,可以用sealed来定义密封类。这样的话,可以防止被其他类继承。
C#中的密封类是指该类不可以被继承。
密封类中的方法不需要定义成密封的。
密封类不能用作基类。因此,它也不能是抽象类。密封类主要用于防止派生。由于密封类从不用作基类,所以有些运行时优化可以使对密封类成员的调用略快。
sealed对于方法表示不能重写该方法,此时,此方法为密封方法。
并不是每个方法都可以声明为密封方法,密封方法只能用于对基类的虚方法进行实现,并提供具体的实现。所以,声明密封方法时,sealed修饰符总是和override修饰符同时使用。
在对基类的虚成员进行重写的派生类上的类成员、方法、字段、属性或事件可以将该成员声明为密封成员。在用于以后的派生类时,这将取消成员的虚效果。方法是在类成员声明中将sealed关键字置于override关键字的前面。
2.结构与接口
结构是一种值类型,通常用来封装一组相关的变量。
向方法传递结构时,结构是通过传值方式传递的,而不是作为引用。
结构的实例化可以不使用new运算符
一个结构可以声明构造函数,但他们必须带参数
一个结构不能从另一个结构或类继承
结构可以实现接口
在结构中初始化实例字段是错误的。
接口:
接口可以将方法、属性、索引器和事件作为成员,但是并不能设置这些成员的具体值,也就是说只能定义。
接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
不能直接实例化接口。
接口不包含方法的实现
类和结构可以从多个接口继承。
接口自身可从多个接口继承。
接口的实现与继承:
接口的实现通过类继承完成,一个类虽然只能继承一个类,但可以继承任意接口。
显示接口成员实现是使用接口名称和一个句点命名该类成员来实现的。
抽象类与接口:
他们的派生类只能继承一个基类
抽象类中可以定义成员的实现。但接口中不可以。
抽象类中可以包含字段、构造函数、析构函数、静态成员或常量等,接口中不可以。
3.集合与索引器
自定义集合需要通过实现System.Collections命名空间提供的集合接口实现
Icollection   定义所有非泛型集合大小/枚举数和同步方法
Icomparer    公开一种比较两个对象的方法
Idictionary    表示建/值对的非通用集合
使用集合类
数组的容量是固定的,而ArrayList的容量可以根据需要自动扩充
ArrayList提供添加、删除和插入某一范围元素的方法、但在数组中只能一次获得或者设置一个元素的值
Array List只有一维形式,而数组可以是多维的。
C#支持一种名为索引器的特殊“属性”,它能够通过实用引用数组元素的方式引用对象。
使用索引器可以类似于数组的方式为对象建立索引;
get取函数返回值,set取函数分配值;
this(代表当前类)关键字用于定义索引器;
value关键字用于定义set索引器所赋予的值;
索引器不必根据整数值进行索引,自行决定如何定义特定的查找机制;
索引器可以被重载;
索引器可以有多个形参,例如对二维数组的访问。
4.异常处理
异常处理类在BCL中定义了很多类,每一个类代表一个指定异常类型。当一个异常发生时,CLR:
1、 创建了该类型的异常对象;
2、 寻找适当的catch 子句来处理它; 
异常处理语句
1、Try语句
Try语句用来指明为避免出现异常而被保护的代码段,并在发生异常时提供代码处理异常。
Try语句是由三个部分组成:
(1)、try块包含为避免出现的异常而被保护的代码。
(2)、catch子句部分含有一个或者多个catch子句。这些是处理代码异常的代码段,它们称为是异常的处理程序
(3)、finally块含有在所有情况下都要被执行的代码,无论有没有异常的发生。
5.委托和匿名方法
委托是C#中的一种引用类型,委托的本质是一个类,定义了方法的类型,是将方法作为参数传递到另一个方法的特殊类。
委托可以认为是持有一个或者多个方法的对象,当委托被调用时,它持有的方法也会被调用。
委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。
委托不是对象,是一种类型。
委托的使用遵循三步走的原则,即定义声明委托,实例化委托,调用委托。 
匿名方法顾名思义就是这类方法的特点是不需要特别去定义函数的名字的。一般我们需要一个函数,但又不想花时间去命名它的时候,就可以使用匿名方法。在 C# 中, 匿名方法通常表现为使用 delegate 运算符和 Lambda 表达式 delegate 运算符创建一个可以转换为委托类型的匿名方法。 匿名方法可以转换为System.Action 和 System.Func<TResult> 等类型,同时指定自定义的参数列表。 Lambda 表达式的本质也是匿名方法。Lambda 表达式提供了一种简洁和富有表现力的方式来创建匿名函数,可以使用 => 运算符来构造 Lambda 表达式。 
匿名方法的优点:
简洁性: 匿名方法可以用更少的代码实现相同的功能。减少代码的复杂性和冗余性,使代码更加简洁。
灵活性: 匿名方法可以作为参数传递给方法,也可以当作返回值返回。
可读性: 匿名方法代码量更少,可以使代码更加清晰易懂,可读性较高。
性能高: 使用 Lambda 表达式可以轻松创建包含异步处理的表达式和语句。
匿名方法的缺点:
重用性低: 匿名方法不能在其它地方进行调用,因此重用性较低。
6.事件
委托的发布和订阅
通过委托来实现事件处理的过程通常需要以下4个步骤
定义委托类型
在订阅者类中
订阅者对象将其事件处理方法链接刀发布者对象的委托成员上。
发布者对象在特定的情况下“激发”委托操作。
事件的发布和订阅
委托可以进行发布和订阅,从而使不同的对象对特定的情况做出反应。
事件中的可用操作比委托要少,我们只能添加(+=)、删除(-=)或调用事件处理程序。
事件被触发时,它调用委托来依次调用调用列表中的方法。
EventHandler类
EventHandler就是一个事件处理器,将一个事件与处理事件的方法联系起来的一种机制。 
声明一个EventArgs的子类,传递参数 
声明委托对象,执行方法,将方法绑定委托对象 
开启EventHandler的委托 
Windows事件
事件在Windows这样的图形界面程序中有着极其广泛的应用,事件响应是程序与用户之间交流的基础。
预处理指令
预处理指令主要用来告诉C#编译器要编译那些代码,并指出如何处理特定的错误和警告。C#中的预处理指令都以“#”开头。
7#region和#endregion
  #region和#endregion 是自定义折叠代码块区域的一个宏定义方法,在代码较多时,我们通常将同类的代码归类,然后将其框在一对#region和#endregion之间。对于较大一点的工程来说非常好用,非常方便自己管理代码。 
#define和#undef
一般情况下会使用#define来定义符号 将符号用作传递给#if指令的表达式,此时的计算结构为true。
#undef用于取消已定义的#define指令。
#if、#else、#elif和#endif这四个指令主要用来判断符号是否已经定义。
#warning和#error
#warning指令用来使开发人员 能够从代码的特定位置生成警告
#error指令用户来是开发人员能够从代码中的特定位置生成错误。
#line指令用来使开发人员能够修改编译器的行号,以及输出错误和警告的文件名。
8泛型
类型参数T可以看作是一个占位符,他不是一个类型,他仅代表某种可能的类型。
泛型接口声明如下
interface 接口名<T>
{
接口体
}
泛型方法
泛型方法声明形式如下
修饰符 void 方法名 <类型参数T>
{
方法体
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值