null第三章 C#面向对象程序设计 第三章 C#面向对象程序设计 内容提要内容提要3.1面向对象编程简介
3.2 定义类
3.3 定义类成员
3.4类的更多内容 什么是面向对象编程 什么是面向对象编程 面向对象编程代表了一种全新的程序设计思路
对象:变量和相关的方法的集合。其中变量表明对象的属性,方法表明对象所具有的行为。
类:通常将属性及行为相同或相似对象归为一类。类可以看成是对象的抽象,代表了此类对象所具有的共同属性和行为
属性和字段:通过属性和字段可以访问对象中包含的数据。
方法:对象的所有行为都可以用方法来描述
静态成员:可以在类的实例之间共享,可以看作是类的全局对象 对象的生命周期 对象的生命周期 每个对象都一个明确定义的生命周期,即从使用类定义开始一直到删除它为止。在对象的
生命周期中,除了“正在使用”的正常状态之外,还有两个重要的阶段:
构造阶段——对象最初进行实例化的时期。这个初始化过程称为构造阶段,由构造函数完成。
析构阶段——在删除一个对象时,常常需要执行一些清理工作,例如释放内存,由析构函数完成。3.1.2 OOP技术3.1.2 OOP技术抽象与接口
继承
多态性
重载
消息和事件 3.2 定义类3.2 定义类C#使用class关键字来定义类。其基本结构如下:
Class MyClass
{
// class members
}
还可以在类定义中指定继承。C#支持类的单一继承,即只能有一个基类,语法如下:
class MyClass : MyBaseClass
{
// class members
} 接口的定义接口的定义接口声明的方式与声明类的方式相似:
interface ImyInterface
{
// interface members
}
接口的继承也可以用与类继承的类似方式来指定。主要的区别是可以使用多个基接口:
public interface IMyInterface : IMyBaseInterface, ImyBaseInterface2
{
// interface members
}3.2.2 Object类3.2.2 Object类所有的.NET类都派生于System.Object。
如果在定义类时没有指定基类,编译器就会自动假定这个类派生于object。
其重要性在于,自己定义的所有类除了自己定义的方法和属性外,还可以访问为Object定义的许多公共或受保护的成员方法。 3.2.3 构造函数和析构函数3.2.3 构造函数和析构函数构造函数
使用下述语法把简单的构造函数添加到一个类中:
class MyClass
{
public MyClass()
{
// Constructor code
}
// rest of class definition
}
这个构造函数与包含它的类同名,且没有参数,这是一个公共函数,所以用来实例化类的对象。构造函数的执行序列构造函数的执行序列为了实例化派生的类,必须实例化它的基类。而要实例化这个基类,又必须实例化这个基类的基类,这样一直到实例化System.Object为止。
如果对一个类使用非默认的构造函数,默认的情况是在其基类上使用匹配十这个构造函数签名的构造函数。如果没有找到这样的构造函数,就使用基类的默认构造函数。析构函数 析构函数 class MyClass
{
~MyClass()
{
//destructor code
}
}
类的析构函数是用类名和前缀~来声明的。当进行无用存储单元收集时,就执行析构函数中的代码,释放资源。在调用这个析构函数后,还将隐式地调用基类的析构函数,包括System. Object根类中的Finalize()调用。3.2.4 接口和抽象类3.2.4 接口和抽象类类似之处:
抽象类和接口都包含可以由派生类继承的成员。
接口和抽象类都不能直接实例化,但可以声明它们的变量。
区别:
派生类只能继承一个基类,即只能直接继承一个抽象类(但可以用一个继承链包含多个抽象类);类可以使用任意多个接口
抽象类可以拥有抽象成员和非抽象成员;接口成员必须都在使用接口的类上执行——它们没有代码体
接口成员被定义为公共的;抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员3.2.5 类和结构3.2.5 类和结构结构与类的区别在于:
结构是值类型,不是引用类型。它们存储在堆栈中或存储为内联,其生存期的限制与简单的数据类型一样。
结构不支持继承。
结构的构造函数的工作方式有一些区别。尤其是编译器总是提供一个无参数的默认构造函数,这是不允许替换的。
使用结构,可以指定字段如何在内存中布局 3.3 定义类成员3.3 定义类成员成员定义
所有成员都有自己的访问级别,用下面的关键字之—来定义:
public——成员可以由任何代码访问。
private——成员只能由类中的代码访问
internal——成员只能由定义它的工程内部的代码访问。
proteded——成员只能由类或派生类中的代码访问。定义字段定义字段
字段用标准的变量声明格式和前面介绍的修饰符来声明
字段也可以使用关键字readonly,表示这个字段只能在执行构造函数的过程中赋值,或由初始化赋值语句赋值。
字段可以使用static关键字声明为静态
可以使用关键字const来创建一个常量 定义方法 定义方法 方法使用标准函数格式,以及可访问性和可选的static修饰符来声明
可以在方法定义中使用下述关键字:
virtual——方法可以重写。
abstract——方法必须重写(只用于抽象类中)。
override——方法重写了一个基类方法(如果方法被重写,就必须使用该关键字)。
extern——方法定义放在其他地方。定义属性定义属性属性定义的方式与字段定义的方式类似,但包含的内容比较多。属性拥有两个类似函数的块,一个块用于获取属性的值,另一个块用于设置属性的值。
这两个块分别用get和set关键字来定义,可以用于控制对属性的访问级别。可以忽略其中的一个块来创建只读或只写属性
属性的基本结构:
public string SomeProperty
{
get
{
return "This is the property value";
}
set
{
// do whatever needs to be done to set the property
}
}3.3.2 类成员的其他议题3.3.2 类成员的其他议题隐藏基类方法
调用重写或隐藏的基类方法 3.3.3接口的实现3.3.3接口的实现接口成员的定义与类成员的定义也相似,但有几个重要的区别:
不允许使用访问修饰符,所有的接口成员都是公共的
接口成员不能包含代码体。
接口不能定义字段成员。
接口成员不能用关键字static,virtual,abstract或sealed来定义。在类中实现接口在类中实现接口执行接口的类必须包含该接口所有成员的执行代码,且必须匹配指定的签名,并且必须是公共的。
可以使用关键字virtual或abstract来执行接口成员,但不能使用static或const,
继承一个实现给定接口的基类,就意味着派生类隐式地支持这个接口 3.4类的更多内容3.4类的更多内容运算符重载
要重载运算符,可给类添加运算符类型成员。指定了要处理多少个操作数,以及这些操作数的类型。一般情况下,操作数的类型与定义运算符的类类型相同,但也可以定义处理混合类型的运算符
下述运算符可以重载:
一元运算符:+,-,!,~,++,--,true,false
二元运算符:+,-,*,/,%,&,|,^,<<,>>
比较运算符:==,!=,<,>,<=,>= 转换运算符转换运算符还可以定义类型之间的隐式和显式转换。如果要在不相关的类型之间转换,这是必须的 3.4.3 高级转换3.4.3 高级转换封箱和拆箱
封箱(boxing)是把值类型转换为System.Object类型,或者转换为由值类型执行的接口类型。拆箱(unboxing)是相反的转换过程
封箱是在没有用户干涉的情况下进行的,但拆箱一个值需要进行显式转换,即需要进行数据类型转换
封箱非常有用,有两个原因。
它允许使用集合中的值类型,集合中项目的类型是object
有一个内部机制允许在值类型上调用objectis运算符 is运算符 is运算符可以检查未知的变量(该变量能用作对象参数,传送给一个方法)是否可为约定的类型,如果可以进行转换,该值就是true。在对对象调用方法前,可以使用该运算符查看执行该方法的对象的类型。is运算符不会检查两个类型是否相同,但可以检查它们是否兼容。
is运算符的语法如下:
is
这个表达式的结果如下:
如果是一个类类型,而也是该类型,或者它继承了该类型,或者它封箱到该类型中,则结果为true。
如果是一个接口类型,而也是该类型,或者它是实现该接口的类型,则结果为true。
如果是一个值类型,而也是该类型,或者它被拆箱到该类型中,则结果为true。as运算符 as运算符 as运算将使用下面的语法,把一种类型转换为指定的引用类型:
as
这只适用于下列情况:
的类型是类型
可以隐式转换为类型
可以封箱到类型.中
如果不能从显式转换为,则表达式的结果就是null。从基类到派生类之间的转换可以显式进行,但这常常是无效的。 3.4.4 深度复制3.4.4 深度复制使用受保护的方法System.Object.MemberwiseClone()进行引用复制,使用一个方法GetCopy()
通过GetCopy()得到的引用复制有一个字段,它引用的对象与源对象相同。
修改GetCopy()方法就可以进行深度复制,但最好使用.NET Framewok的标淮方式。
实现ICloneable接口,该接口有一个方法Clone(),这个方法不带参数,返回一个对象类型,其签名和GetCopy()方法相同。3.4.5 定制异常3.4.5 定制异常 .NET框架提供了一种用于
报告
软件系统测试报告下载sgs报告如何下载关于路面塌陷情况报告535n,sgs报告怎么下载竣工报告下载
错误的标准机制,称之为结构化异常处理(SEH,Structured Exception Handling)。
异常是描述错误的类。
.NET架使用异常来报告错误,并且在代码中也可以使用异常。
编写代码来监视任何代码段生成的异常。
在处理异常时要标识三个代码块:
使用异常处理的代码块;
在处理第一个代码块时,如果找到某个异常,就执行代码块
在处理完异常之后执行选择的代码块。3.4.5 定制异常3.4.5 定制异常在C#中,异常的生成称之为抛出(throwing)异常。
被通知抛出了一个异常则称之为捕获(catching)异常
处理完异常之后执行的代码块是终结(finally)代码块
指定异常处理指定异常处理C#的关键字try指定让某个代码块监视代码执行时抛出的任何异常。使用try关键字很简单。使用时,try关键字后面跟一对花括号,花括号中的语句用来监视代码执行时抛出的异常。
try
{
//place satements here
}
在执行try代码块中的任何语句时,如果有异常抛出,就可以在代码中捕获该异常并相应进行处理。捕获异常 捕获异常 最简单形式的catch代码块捕获前面try代码块中代码抛出的任何异常。catch代码块的结构类似try代码块:
try
{
//place statements here
}
catch
{
//place statements here
}捕获特定类的异常捕获特定类的异常try
{
//place statements here
}
catch(Exception thrownException)
{
//palce statements here
}
出现异常之后进行消除出现异常之后进行消除try
{
//open files
//read files
}
catch
{
//catch exceptions
}
finally
{
//close files
}由.NET框架定义的异常 由.NET框架定义的异常 OutOfMemoryException异常
StackOverflowException异常
NullReferenceException异常
TypeInitializationException异常
InvalidCastException异常
ArrayTypeMismatchException异常
IndexOutOfRangeException异常
DivideByZeroException异常
0verflowException异常使用自定义的异常 使用自定义的异常 System.Exception类包含四个只读属性,在catch代码块中可以使用这些属性来获取有关抛出的异常的更多信息:
Message属性包含对异常原因的描述。
InnerException属性包含引起抛出当前异常的异常。
StackTrace属性包含一个字符串,用它来显示抛出异常时正在使用的方法调用的堆栈。
最后,堆栈服踪将跟踪所有返回CLR原始调用的路线至应用程序的Main()方法、TargetSite属性包含抛出异常的方法 抛出自定义的异常抛出自定义的异常可以用C#的throw关键字抛出自定义的异常。
throw关键字后面必须跟一个表达式,该表达式的值为类System.Exception或者其派生类的一个对象。 3.5 本章
小结
学校三防设施建设情况幼儿园教研工作小结高血压知识讲座小结防范电信网络诈骗宣传幼儿园师德小结
3.5 本章小结 面向对象编程
OOP中的技术
基本的类定义
接口的定义
如何定义字段、属性和方法等类成员
如何进行运算符重载。
封箱(boxing)、拆箱(unboxing)
is和as运算符的使用方法
如何深度复制。
如何定制异常。