资源预览内容
第1页 / 共36页
第2页 / 共36页
第3页 / 共36页
第4页 / 共36页
第5页 / 共36页
第6页 / 共36页
第7页 / 共36页
第8页 / 共36页
第9页 / 共36页
第10页 / 共36页
亲,该文档总共36页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第三章 C#面向对象程序设计,内容提要,3.1面向对象编程简介 3.2 定义类 3.3 定义类成员 3.4类的更多内容,什么是面向对象编程,面向对象编程代表了一种全新的程序设计思路 对象:变量和相关的方法的集合。其中变量表明对象的属性,方法表明对象所具有的行为。 类:通常将属性及行为相同或相似对象归为一类。类可以看成是对象的抽象,代表了此类对象所具有的共同属性和行为 属性和字段:通过属性和字段可以访问对象中包含的数据。 方法:对象的所有行为都可以用方法来描述 静态成员:可以在类的实例之间共享,可以看作是类的全局对象,对象的生命周期,每个对象都一个明确定义的生命周期,即从使用类定义开始一直到删除它为止。在对象的 生命周期中,除了“正在使用”的正常状态之外,还有两个重要的阶段: 构造阶段对象最初进行实例化的时期。这个初始化过程称为构造阶段,由构造函数完成。 析构阶段在删除一个对象时,常常需要执行一些清理工作,例如释放内存,由析构函数完成。,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类,所有的.NET类都派生于System.Object。 如果在定义类时没有指定基类,编译器就会自动假定这个类派生于object。 其重要性在于,自己定义的所有类除了自己定义的方法和属性外,还可以访问为Object定义的许多公共或受保护的成员方法。,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.5 类和结构,结构与类的区别在于: 结构是值类型,不是引用类型。它们存储在堆栈中或存储为内联,其生存期的限制与简单的数据类型一样。 结构不支持继承。 结构的构造函数的工作方式有一些区别。尤其是编译器总是提供一个无参数的默认构造函数,这是不允许替换的。 使用结构,可以指定字段如何在内存中布局,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.3接口的实现,接口成员的定义与类成员的定义也相似,但有几个重要的区别: 不允许使用访问修饰符,所有的接口成员都是公共的 接口成员不能包含代码体。 接口不能定义字段成员。 接口成员不能用关键字static,virtual,abstract或sealed来定义。,在类中实现接口,执行接口的类必须包含该接口所有成员的执行代码,且必须匹配指定的签名,并且必须是公共的。 可以使用关键字virtual或abstract来执行接口成员,但不能使用static或const, 继承一个实现给定接口的基类,就意味着派生类隐式地支持这个接口,3.4类的更多内容,运算符重载 要重载运算符,可给类添加运算符类型成员。指定了要处理多少个操作数,以及这些操作数的类型。一般情况下,操作数的类型与定义运算符的类类型相同,但也可以定义处理混合类型的运算符 下述运算符可以重载: 一元运算符:+,-,!,+,-,true,false 二元运算符:+,-,*,/,%,|, 比较运算符:=,!=,=,转换运算符,还可以定义类型之间的隐式和显式转换。如果要在不相关的类型之间转换,这是必须的,3.4.3 高级转换,封箱和拆箱 封箱(boxing)是把值类型转换为System.Object类型,或者转换为由值类型执行的接口类型。拆箱(unboxing)是相反的转换过程 封箱是在没有用户干涉的情况下进行的,但拆箱一个值需要进行显式转换,即需要进行数据类型转换 封箱非常有用,有两个原因。 它允许使用集合中的值类型,集合中项目的类型是object 有一个内部机制允许在值类型上调用object,is运算符,is运算符可以检查未知的变量(该变量能用作对象参数,传送给一个方法)是否可为约定的类型,如果可以进行转换,该值就是true。在对对象调用方法前,可以使用该运算符查看执行该方法的对象的类型。is运算符不会检查两个类型是否相同,但可以检查它们是否兼容。 is运算符的语法如下: is 这个表达式的结果如下: 如果是一个类类型,而也是该类型,或者它继承了该类型,或者它封箱到该类型中,则结果为true。 如果是一个接口类型,而也是该类型,或者它是实现该接口的类型,则结果为true。 如果是一个值类型,而也是该类型,或者它被拆箱到该类型中,则结果为true。,as运算符,as运算将使用下面的语法,把一种类型转换为指定的引用类型: as 这只适用于下列情况: 的类型是类型 可以隐式转换为类型 可以封箱到类型.中 如果不能从显式转换为,则表达式的结果就是null。从基类到派生类之间的转换可以显式进行,但这常常是无效的。,3.4.4 深度复制,使用受保护的方法System.Object.MemberwiseClone()进行引用复制,使用一个方法GetCopy() 通过GetCopy()得到的引用复制有一个字段,它引用的对象与源对象相同。 修改GetCopy()方法就可以进行深度复制,但最好使用.NET Framewok的标淮方式。 实现ICloneable接口,该接口有一个方法Clone(),这个方法不带参数,返回一个对象类型,其签名和GetCopy()方法相同。,3.4.5 定制异常,.NET框架提供了一种用于报告错误的标准机制,称之为结构化异常处理(SEH,Structured Exception Handling)。 异常是描述错误的类。 .NET架使用异常来报告错误,并且在代码中也可以使用异常。 编写代码来监视任何代码段生成的异常。 在处理异常时要标识三个代码块: 使用异常处理的代码块; 在处理第一个代码块时,如果找到某个异常,就执行代码块 在处理完异常之后执行选择的代码块。,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框架定义的异常,OutOfMemoryException异常 StackOverflowException异常 NullReferenceException异常 TypeInitializationException异常 InvalidCastException异常 ArrayTypeMismatchException异常 IndexOutOfRangeException异常 DivideByZeroException异常 0verflowException异常,使用自定义的异常,System.Exception类包含四个只读属性,在catch代码块中可以使用这些属性来获取有关抛出的异常的更多信息: Message属性包含对异常原因的描述。 InnerException属性包含引起抛出当前异常的异常。 StackTrace属性包含一个字符串
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号