资源预览内容
第1页 / 共72页
第2页 / 共72页
第3页 / 共72页
第4页 / 共72页
第5页 / 共72页
第6页 / 共72页
第7页 / 共72页
第8页 / 共72页
第9页 / 共72页
第10页 / 共72页
亲,该文档总共72页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
C#C# C# 程序设计大学教程程序设计大学教程面向对象与对象模型面向对象与对象模型面向对象与对象模型面向对象与对象模型C#C#C#4.1 4.1 面象对象的概念面象对象的概念面象对象的概念面象对象的概念4.1.1 面向对象基本原理4.1.2 类和对象的概念4.1.3 UML和对象建模 4.1.4 简评面向对象C#C#C#4.1.1 4.1.1 面向对象基本原理面向对象基本原理面向对象基本原理面向对象基本原理 面向对象方法学对复杂的客观世界进行抽象和认识,形成如下基本观点:1)客观世界(事物)由各种各样的实体组成,这些实体称为对象。例如:司机、卡车、轿车等。2)每个对象都具有各自的内部状态和运动规律(自主性);而且,在外界其他对象或环境的影响下,对象本身根据具体事件做出不同的反应,进行对象间的交互(消息机制)。C#C#C#4.1.1 4.1.1 面向对象基本原理面向对象基本原理面向对象基本原理面向对象基本原理3)按照对象的属性和运动规律的相似性,可以将相近的对象划分为一类。例如:卡车、轿车这一类对象可以划分为汽车类。(一般-特殊结构/继承关系)4)复杂的对象由相对简单的对象通过一定的方式组成。例如:汽车对象可以由发动机、轮子、底盘等多个对象组成。(整体-部分结构/聚合关系)5)不同对象的组合及其间的相互作用和联系构成了各种不同的系统,构成了人们所面对的客观世界。C#C#C#4.1.2 4.1.2 类和对象的概念类和对象的概念类和对象的概念类和对象的概念0、基本概念(1)类(class):具有相同属性和操作的一组对象的集合,为属于该类的全部对象提供了统一的抽象描述。类似于模版。体现了抽象原则。(2)对象:问题域或实现域中某些事物的一个抽象,反映了该事物在系统中需要保存的信息和能够发挥得作用,是一组属性和有权对这组属性进行存取和修改的一组操作的封装体。(3)属性:描述对象静态特征的数据项。(4)操作:描述对象动态特征(行为)的动作序列。C#C#C#4.1.2 4.1.2 类和对象的概念类和对象的概念类和对象的概念类和对象的概念1 1对象的封装性(对象的封装性(encapsulationencapsulation)2 在OOP中,最基本的理解是把对象的数据和代码组合在同一个结构中,这就是对象的封装特性。将对象的数据字段封闭在对象的内部,使得外部程序必须而且只能使用正确的方法才能访问要读写的数据字段。封装性意味着数据和代码一起出现在同一结构中,如果需要的话,可以在数据周围砌上“围墙”,只有用对象类的方法才能在“围墙”上开个“窗口”。利用封装性,可以把相关的数据和代码结合在一起,并隐藏了实现细节。(黑盒子)(相对独立性) (使软件错误局部化,减少差错难度)C#C#C#4.1.2 4.1.2 类和对象的概念类和对象的概念类和对象的概念类和对象的概念2 2 对象的继承性(对象的继承性(inheritanceinheritance) 继承性是OOP中最重要的特性之一。指一个类(派生类)能够从另一个类(基类)中自动或隐含地获取属性和方法。继承的好处是能共享代码,继承后,父类的所有字段和方法都将存在于子类中。(软件复用) 继承关系是可传递的。 C#只支持单继承。 多继承容易产生“命名冲突”问题。C#C#C#4.1.2 4.1.2 类和对象的概念类和对象的概念类和对象的概念类和对象的概念3 3对象的多态性(对象的多态性(polymorphismpolymorphism) 多态性描述的是如下现象:如果几个子类都重新定义了父类的某个函数(都用相同的函数定义),当消息被发送到一个子类对象时,该消息会由于不同的子类而被解释为不同的操作。 与多态性有关的概念:重载(overload)动态绑定(dynamic binding)。C#C#C#4.1.2 4.1.2 类和对象的概念类和对象的概念类和对象的概念类和对象的概念4、聚合(aggregation) 一个复杂的对象以若干比较简单的对象作为其组成部分,这称为聚合,反映了整体-部分结构。 聚合实现方式: (1)用部分对象作为整体对象的一个属性。此时一个部分对象只能隶属于唯一的整体对象,表示紧密、固定的聚合关系。 (2)独立地定义和创建整体对象和部分对象,并在整体对象中设置一个属性,它的值是部分对象的对象标识。此时整体对象和部分对象可以有不同的生存期,表示松散、灵活的聚合关系。C#C#C#4.1.2 4.1.2 类和对象的概念类和对象的概念类和对象的概念类和对象的概念5、消息(message) 消息是对象之间在一次交互中所传送的信息。 封装使对象成为一些各司其职、互不干扰的独立单位;消息通信为它们提供了唯一合法的动态联系途径,使它们的行为能够相互配合,构成一个有机的、运动的系统。C#C#C#4.1.3 4.1.3 UMLUML和对象建模和对象建模1 1模型与建摸模型与建摸2 软件模型除了用于系统设计还可以用在很多的方面,例如预期系统的质量、在系统的某些方面变化时推理特定的属性、测试关键的系统特征等。模型可以先开发出来用于指导物理系统的开发,或者也可以由一个已存在的系统或者开发中的系统产生,作为理解系统行为、优化系统实现的手段。C#C#C#4.1.3 4.1.3 UMLUML和对象建模和对象建模 从软件建模技术的发展过程中,人们认识到建模语言是一种图形化的文档描述性语言,利用它可以解决在软件建模过程中存在的沟通障碍问题。面向对象建模中使用了一些带有图形符号的建模语言,就好像是五线谱中的音符一样。 C#C#C#4.1.3 4.1.3 UMLUML和对象建模和对象建模2 2统一建模语言统一建模语言UMLUML UML是 统 一 建 模 语 言 ( The Unified Modeling Language)的英文缩写,UML是一个通用的可视化建模语言,用于对软件进行描述、可视化处理、构造和建立软件系统制品的文档。它可以把人们对所需要构建系统的想法和理解记录下来,以便用于对系统的分析、设计、研究、配置和维护。UML适用于各种软件开发方法、软件生命周期的各个阶段、各种应用领域以及各种开发工具,是一种总结了以往建模技术的经验并吸收当今优秀成果的标准建模方法。C#C#C#4.1.3 4.1.3 UMLUML和对象建模和对象建模3、常用建模软件(1)IBM Rational Rose(2)Microsoft Office Visio 2003 (3)Enterprise Architect(4)PowerDesigner C#C#C#4.1.4 4.1.4 简评面向对象简评面向对象简评面向对象简评面向对象对象概念对程序设计中的问题求解和模型建立都具有莫大的好处,在设计优秀合理的情况下尤其如此。用来创建对象的代码还可能用于多个应用程序。OOP的另一优点是对代码结构的影响。但是OOP也存在一些固有的缺点。 C#C#C#4.2 4.2 类和对象类和对象类和对象类和对象4.2.1 类的声明及其成员类的声明及其成员4.2.2 对象和对象的生命周期对象和对象的生命周期C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员1类的声明2attributes class-modifiers class identifier class-base class-body ; 其中attributes、class-modifiers、class-base和class-body是可选的。attributes为属性集,class-modifiers为类的修饰符, class为类声明的关键字,后面是类的名称,class-base和class-body表示继承方式和基类名。类的修饰符控制了类的访问性,可以是以下几种之一或者是它们的组合(但同一修饰符不允许出现多次。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员1.1 类的修饰符internal 类只能在当前项目中访问(缺省)public 类可以在任何地方访问internal abstract 类只能在当前项目访问, 不完整,不能实例化,只能做基类public abstract 类可以在任何地方访问 不能实例化,只能派生internal sealed 类只能在当前项目中访问, 只能实例化,不能派生public sealed 类可以在任何地方访问, 只能实例化,不能派生C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员1.2 几点说明(1)C#编译器不允许派生类的可访问性高于其基类的可访问性。(2)C#中如果类定义时没有指定基类,则该类默认继承于System.Object。(3)C#的类定义中,类只能有一个基类,但可以有多个接口。(4)如果继承了一个抽象类,就必须执行所继承的所有抽象成员,除非派生类也是抽象类。(5)抽象类不必须包含抽象成员。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员2类成员 在类定义中,也提供了该类中所有成员的定义。从定义的形式来看,类成员可以分为两大类:类本身所声明的及从基类中继承而来的。类的成员包含以下几种类型:成员常量,代表了与类相关的常数数据。字段,它是类的变量。成员方法,实现了类中的复杂计算和行为C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员属性,定义了命名的属性和与对这个属性进行读写的相关行为。事件,它定义了由类产生的事件公告。索引指示器,允许类的实例通过与数组相同的方法来索引。操作符,定义了可以被应用于类的实例上的表达式操作符。构造函数,执行需要对类的实例进行初始化的动作。析构函数,执行在类的实例被销毁前要实现的动作。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员3成员的访问(1)公共成员它通过在成员声明中加public修饰符来定义。“公共的”直觉意义是“无限制访问”,定义的成员可以在类的外部进行访问。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员(2)保护成员保护成员通过在成员声明中使用protected修饰符来定义。为了方便派生类的访问,但又不希望其他无关类随意访问,这时就可以使用protected修饰符,将成员声明为保护的。(3)内部成员内部成员通过在成员声明中使用internal修饰符来定义。该成员只能被包中的代码访问,而包之外的代码无法访问。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员(4)私有成员 私有成员通过在成员声明中使用private修饰符来定义。C#中的私有成员只有类中的成员可以访问,在类的外部(包括其派生类)是禁止直接访问私有成员的。这也是C#中成员声明的默认方式,即若在成员声明时没有使用任何访问修饰符,那么C#自动将它限定为私有成员。(5)保护的内部成员这种成员实际上是同时使用了protected和internal这两个修饰符来定义的,因此,由这两者共同限制成员的访问。也就是说,该成员只能被该类本身或同一包中的派生子类访问,其他包中该类的派生类无法访问。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员4静态成员和非静态成员5 类的成员可以是静态成员或非静态成员,C#中用关键字static作为静态修饰符。6 通常来讲,静态成员是属于类所有的,而非静态成员是属于对象的(类的实例)。7 若成员前没有使用static修饰符,那么它就声明为一个非静态成员,即类成员默认为非静态成员。8 非静态成员有时也被称为实例成员。 C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员4.1 静态/类成员特征(1)一个静态数据成员确定一个存储位置。不管该类创建了多少实例,类的静态数据成员只有一个备份。(2)使用“类名.静态数据成员名字”(3)静态功能成员(方法、属性、索引、操作符、构造函数)不会在指定的实例中操作,不能在静态功能成员中使用关键字this。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员(4)静态成员属于类,可以在类的所有实例间共享。静态属性和静态字段可以访问独立于任何对象实例的数据;静态方法可以执行与对象类型相关但与特定实例无关的命令,在使用静态成员时,甚至不需要实例化,如Console.ReadLine()、Console.WriteLine()、File.Copy()。(5)常量成员默认是静态的。(6)析构函数不能是静态的。(7)静态成员可以是私有的。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员4.2 非静态/实例成员特征(1)必须使用“对象名.成员名”来访问(2)类的每个实例都包括类的非静态成员的独立备份(3)在非静态功能成员中可以使用关键字thisC#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员4.3 this指针(1)this指向当前对象(2)实例函数的第一个参数是隐式的this指针,this指针使得可以隐式地引用本对象的成员(3)静态成员函数不会把this指针作为隐式参数来传递,因此,静态成员不能直接访问类的实例成员(4)静态成员本质上只能访问其他静态成员;实例成员可以访问类的实例成员和静态成员(5)this指针是只读的C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员5类和结构的比较6 结构(struct)和类有很多相似的地方,在结构中同样可以包含字段成员和方法成员。在C+中的struct和class几乎没有任何差别,惟一的差别在于:struct中的成员默认是公有的,而class中的成员默认是私有的。但在C#中,这两种类型的内核发生了本质的变化:struct是值类型的,而class是引用类型的。 C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员(1 1)值和引用)值和引用 结构是值类型,值类型是在栈上分配的或者联机作为其他对象的一部分。从栈的角度来看,结构是应该作为基本类型对待的对象。 类是引用类型,它们的存储位置分配在堆中。类的性质变化很大,它们通常用于实现更多处理能力的需要。它们能支持属性角色的类成员。类用于实现某个商业逻辑,而不是仅支持相关数据或类似基本类型的对象。C#C#C#4.2.1 4.2.1 类的声明及其成员类的声明及其成员类的声明及其成员类的声明及其成员(2 2)继承性)继承性 在继承性(将在下一章阐明其概念)方面,结构要比类的限制多得多。结构不允许从另一结构或者类继承。结构是隐式地限制为sealed,(如果类限制为sealed,那么它也是不能派生新类的)但它们能够实现接口。而类是支持继承的(被标识为sealed的除外),可以按照继承关系形成一个多层次的关系框架,提高代码的重用率。 C#C#C#4.2.1 4.2.1 对象和对象的生命周期对象和对象的生命周期对象和对象的生命周期对象和对象的生命周期1 对象的存储 在谈到类和结构时,通常会指出对象是存储在堆中的。一个类可以创建多个对象实例,每个对象实例独自占有一定的资源。似乎非常简单,但这里要强调一点,并非所有的对象都完全按照类的成员组成来创建,例如静态字段就不在对象实例中;所有的方法都只存储一次,并与类关联,方法的代码对于该类所有对象都是一样的。 C#C#C#4.2.1 4.2.1 对象和对象的生命周期对象和对象的生命周期对象和对象的生命周期对象和对象的生命周期2 对象的生命周期 对象是通过类动态创建的,从产生到消失,有一个明确的生命周期。在对象的生命周期中,除了“正在使用”的正常状态之外,还有两个重要的阶段,即构造和析构阶段,也称创建和销毁阶段。 构造阶段构造阶段 对象最初进行实例化的时期。这个初始化过程就称为构造阶段,通过构造函数完成。 析构阶段析构阶段 在删除一个对象时,常常需要执行一些清理工作,如释放内存,该过程就称为析构阶段。这些工作是由析构函数完成。C#C#C#4.2.1 4.2.1 对象和对象的生命周期对象和对象的生命周期对象和对象的生命周期对象和对象的生命周期(1)构造函数 构造函数用于执行类的实例的初始化。每个类都有构造函数,即使我们没有声明,编译器也会在后台自动为我们提供一个默认的构造函数。 (2)静态构造函数 静态构造函数也是一个实现对类进行初始化的功能成员。这种构造函数只执行一次,主要用来初始化类中的静态变量。不能带参数。一个类只能有一个静态构造函数。只能访问静态数据成员。C#C#C#4.2.1 4.2.1 对象和对象的生命周期对象和对象的生命周期对象和对象的生命周期对象和对象的生命周期(3)析构函数 前面介绍了构造函数,可以在创建类的实例时,完成初始化工作。而析构函数顾名思义就是在删除类实例时执行的操作。当不再需要某个类的实例时,我们希望确保它所占的存储空间能被收回。C#中提供了析构函数,专门用于释放被占用的系统资源。 析构函数不能继承,不能显式调用。C#C#C#4.3 4.3 属性和索引属性和索引属性和索引属性和索引4.3.1 属性4.3.2 索引C#C#C#4.3.1 4.3.1 属性属性属性属性1 属性的定义 属性是对类的字段(一般为私有变量)提供特定访问的类成员。由于是类的成员,因此可以访问私有实例变量,而不必使用繁琐的方法。同时,又不会危害类中私有变量保护和隐藏的数据,因为属性在类中是按一种与方法类似的方式执行的。 属性可以使得私有变量可读而不可写、可写而不可读、可读可写。 value为隐式关键字,根据上下文取值。C#C#C#4.3.1 4.3.1 属性属性属性属性2 属性访问器 C#中提供了两种类型的访问器。第一个是获取属性的get访问器;另一个是修改属性的set访问器。而且它们在定义中没有先后之分。 get访问器:get访问器获得属性值,并将它返回给调用的程序。在访问器中并非只能控制与属性名称相关的字段,也可以利用get访问器进行类的状态管理等。 set访问器:set访问器用于修改属性值,其他与get访问器类似。 C#C#C#4.3.1 4.3.1 属性属性属性属性3 静态属性 当属性声明中包含static修饰符时,那么这个属性为静态属性,反之,就被称为实例属性。在很多方面,静态属性和其他静态成员的限制相同,没有更多新的内容。但请记住:它只能访问类的静态/类成员。 非静态属性可访问静态成员,一般不这样做。 C#C#C#4.3.1 4.3.1 属性属性属性属性4 属性的限制 对于属性在使用时的限制,我们分两个方面来比较。 (1)属性和字段很相似,但不能完全像字段一样使用。不能声明为const;不能在一个表达式中声明多个属性;不能通过set访问器初始化;不能作为方法调用中的ref或out参数传递;属性在使用前要先赋值。 (2)在属性的定义中,格式比较严格,在get和set访问器之外,不能进行任何操作。可以包含代码;声明属性的类型不能为void,也不能省略;声明属性的类型不能超过一个。C#C#C#4.3.1 4.3.1 属性属性属性属性class Test private int age; public int Age getreturn age; set if (value 0) Console.WriteLine(wrong); elseage = value; C#C#C#4.3.2 4.3.2 索引索引索引索引0、作用索引使得程序员可以像访问数组一样使用的方式访问对象成员。如DataTable对象的rows属性可以以二维数组的形式访问,且对列提供多种索引格式;类似对象还有很多。C#C#C#4.3.2 4.3.2 索引索引索引索引1 索引的申明索引的声明形式如下:attributes type thistype indexget/执行代码return set/执行代码 /表示式(可以使用关键字value)C#C#C#4.3.2 4.3.2 索引索引索引索引2 索引访问器 在索引中有两个访问器:get和set访问器。这一点和属性非常相似,而且,访问器发生作用的方式也和属性相同。可以将索引分为以下3类:读写索引读写索引 索引中包含set和get访问器,对索引拥有读和写的方式。只读索引只读索引 索引中只包含get访问器,此时,只能通过索引读取内容。只写索引只写索引 索引只包含set访问器,在这种情况下,就只能使用索引写内容。 C#C#C#4.3.2 4.3.2 索引索引索引索引3 多索引 在同一类中可以使用多个索引。要定义多索引就必须通过不同的签名来惟一标识每个索引。索引签名和下一节将要讲到的方法签名类似,索引签名由索引中的参数数量、类型和顺序组成,而方法签名还要增加一项:方法名称。 见课本101页例子。C#C#C#4.4 4.4 方法方法方法方法4.4.1 方法定义4.4.2 方法中的字段4.4.3 实例方法与静态方法4.4.4 方法的参数C#C#C#4.4.1 4.4.1 方法定义方法定义方法定义方法定义 方法是类中重要的组成部分,方法定义包括一个方法头和一个方法体。方法头定义决定了其他程序部分访问和调用此方法的方式(返回类型、参数个数等)。方法体包含了调用方法时执行的语句。 方法用来表现对象的动态行为/操作,或对某事件的响应,或对外界提供访问数据成员的接口,或进行资源的申请与释放C#C#C#4.4.1 4.4.1 方法定义方法定义方法定义方法定义方法修饰符abstract 只是方法特征标记,没有实现extern 外部方法internal 本程序中的代码可以访问new 隐藏同名称的基类方法override 当虚基类方法通过基类引用调用时,由派生类实 现基类中的虚方法;基类中与该方法同名的方法 声明为virtualprivate 只有本类的代码可以访问该方法protected 只有本类和派生类可以访问该方法static 不属于任何实例,通过“类名.方法名”来调用virtual 虚方法,允许派生类中同名方法定义override, 并且只有当这个方法通过该类引用时才被调用C#C#C#4.4.2 4.4.2 方法中的字段方法中的字段方法中的字段方法中的字段 在方法中,可以声明自己的局部变量(局部字段),另外每个方法还确定了形式参数,它是在方法声明中定义的参数。一个方法中可以有零个或多个被逗号分开的形式参数。 方法中定义的局部变量,只有在方法主体内可用,方法中定义的形式参数和局部变量一样,作用域也只限于方法主体内。 C#C#C#4.4.3 4.4.3 实例方法与静态方法实例方法与静态方法实例方法与静态方法实例方法与静态方法1 实例方法 实例方法的执行与特定的对象相关联,所以,似乎每个对象都在内存中有一个特定的实例方法拷贝。但是情况并非如此,因为这样会白白地消耗大量的内存空间。实际上,微软在实现对象的存储时,使相同类的所有对象都共享每个实例方法的一个拷贝。 实例方法在给定实例上操作,并且这个实例可以使用this关键字来访问。实例方法必须使用对象尾随一个点操作符的方式调用。C#C#C#4.4.3 4.4.3 实例方法与静态方法实例方法与静态方法实例方法与静态方法实例方法与静态方法2 静态方法 当方法声明中包括一个static修饰符时,该方法就称为静态方法。对于静态方法的调用,有如下3种方式: 从方法所属的类的一个对象中调用。此时不需要引用任何类名或对象名。 如果是外部调用,可以使用“类名.方法名”来调用。 外部调用类的静态方法时,也可以使用对象名加点操作符再加方法名。 (不建议这样做) 静态方法不能对指定的实例进行操作;在静态方法中不能使用this关键字;不能使用virtual、abstract或override修饰静态方法。C#C#C#4.4.4 4.4.4 方法的参数方法的参数方法的参数方法的参数1 值参数 值参数没有修饰符(不是类型)。通常,当在参数声明中没有指定它的种类时,参数种类就默认为值参数。 方法中访问值参数的一个拷贝,而不是直接访问值参数本身。(数组也一样,但略不同) 在方法中,它与局部变量相对应,这个局部变量从方法调用的相应赋值来获得它的初始数值。C#C#C#4.4.4 4.4.4 方法的参数方法的参数方法的参数方法的参数2 引用参数 引用参数使用关键字ref开头,然后再确定引用参数的数据类型。 当传递给方法一个引用类型的参数时,引用参数不会创建新的存储单元,在方法主体内修改引用参数也会修改作为参数传递的原始变量。 C#不支持引用变量,除非为unsafe代码。如在C+允许int &a=b; 当调用带有ref参数的方法时,对应的实参也要带有ref关键字。 可以使用ref关键字定义方法的重载。C#C#C#4.4.4 4.4.4 方法的参数:引用参数举例方法的参数:引用参数举例方法的参数:引用参数举例方法的参数:引用参数举例 public class Program static void swap(int a, int b) int t;t = a;a = b;b = t;return; static void swap(ref int a, ref int b) int t;t = a;a = b;b = t;return; static void Main(string args) int a = 3, b = 5; swap(a, b);Console.WriteLine(a.ToString() + + b.ToString(); swap(ref a,ref b);Console.WriteLine(“0,1”,a,b); Console.ReadLine(); C#C#C#4.4.4 4.4.4 方法的参数方法的参数方法的参数方法的参数3 输出参数 输出参数有一个明显的特征:out修饰符。与上面两种参数相比,这种参数形式不要求预先对其赋值,但返回前一定要赋值。当然,若该变量在调用前已经赋过值了,也可以作为输出参数传递,只是在方法调用的内部仍然把它当做没有赋过值。这样也就要求,无论是哪种情况,在方法内必须先对out变量赋值,然后才能合法地调用,否则将导致一个编译错误。 可以使用out定义方法的重载,但不能同时使用ref和out定义重载。 若调用带有out参数的方法,对应的实参也要带上out关键字。C#C#C#4.4.4 4.4.4 方法的参数方法的参数方法的参数方法的参数4 参量参数 主要用来传递个数不确定的多个参数,以前常用带有“缺省参数”的方法、函数重载或者使用“数组+元素个数”作为方法参数来实现,但在一定程度上造成了资源浪费。 参量参数可以把一维数组或者不规则数组传递给方法,在方法声明的参数列表中,这类参数必须以params打头,不能用ref或out修饰。 参量参数只能是一维数组,如string、string,但string,不可以。 方法可以同时定义多种类型的形式参数,但参量参数必须是最后一个参数。C#C#C#4.4.4 4.4.4 方法的参数:参量参数举例方法的参数:参量参数举例方法的参数:参量参数举例方法的参数:参量参数举例 class Program static int sum(params int array) int result = 0; foreach (int temp in array) result += temp; return result; static void Main(string args) Console.WriteLine(sum(3,5,7,10); Console.ReadLine(); C#C#C#4.4.5 4.4.5 虚方法(补充)虚方法(补充)虚方法(补充)虚方法(补充) 虚方法使用virtual关键字修饰,不能同时static/abstract/override修饰,且不能为private。 虚方法可以有具体的实现,也可以没有任何实现(即方法体为空,但不能省略),也可以在派生类中改变其实现(即override)。C#C#C#4.4.6 4.4.6 覆盖方法(补充)覆盖方法(补充)覆盖方法(补充)覆盖方法(补充) 覆盖方法使用override关键字修饰,不能同时使用new/static/virtual修饰,可以同时使用abstract关键字修饰。 覆盖方法用来改变从基类继承的virtual方法和abstract方法的具体实现。 覆盖方法不能改变virtual/abstract方法的可访问性。 在覆盖方法中可以使用base关键字访问基类的成员。 可以使用override对基类中已经override的方法再一次覆盖。C#C#C#4.4.7 4.4.7 封固方法(补充)封固方法(补充)封固方法(补充)封固方法(补充) 封固方法使用sealed关键字修饰,可以同时使用override修饰,主要用来防止在本类的派生类中进一步覆盖。C#C#C#4.4.8 4.4.8 抽象方法(补充)抽象方法(补充)抽象方法(补充)抽象方法(补充) 抽象方法使用abstract关键字修饰,不能同时使用virtual修饰。 不能在非抽象类中定义抽象方法。 抽象方法的定义不能有方法体,空方法体也不可以。 可以在派生类中使用override对抽象方法进行覆盖。C#C#C#4.4.9 4.4.9 外部方法(补充)外部方法(补充)外部方法(补充)外部方法(补充) 外部方法使用extern修饰,该方法一般是在外部使用其他非C#语言实现的非托管代码,在本类中只是声明该方法,没有方法体,且必须同时使用static修饰,不能同时使用abstract修饰。 extern的典型应用是与DllImport配合,允许外部方法通过动态链接库实现。C#C#C#4.4.9 4.4.9 外部方法(补充):举例外部方法(补充):举例外部方法(补充):举例外部方法(补充):举例 using System; using System.Runtime.InteropServices; class MainClass DllImport(User32.dll) public static extern int MessageBox(int h, string m, string c, int type); static int Main() string myString; Console.Write(Enter your message: ); myString = Console.ReadLine(); return MessageBox(0, myString, My Message Box, 0); C#C#C#4.4.9 4.4.9 外部方法(补充):举例外部方法(补充):举例外部方法(补充):举例外部方法(补充):举例C#C#C#4.5 4.5 重载重载重载重载4.5.1 重载方法4.5.2 重载操作符C#C#C#4.5.14.5.1 重载方法重载方法重载方法重载方法 方法重载(overload)是指程序在一个类中定义多个名称相同但具有不同签名(主要体现在参数个数和参数类型的不同上)的方法/函数。 C#中对大量方法/函数进行了重载。如Console.WriteLine()可输出多种类型参数。C#C#C#4.5.2 4.5.2 重载操作符重载操作符重载操作符重载操作符/ /运算符运算符运算符运算符 重载操作符/运算符有重新定义C#操作符的功能。操作符重载概念的提出是为了让代码看起来更加自然、表达式更紧凑且更易于编写。赋予操作符更丰富的含义。 “+”操作符在C#中已经进行了重载,使其不仅能够对数值类型操作数进行求和,还能够连接字符串。 只能为当前类的对象进行操作符的重载,且至少一个参数应为当前类的实例。如下面的例子: C#C#C#4.5.2 4.5.2 重载操作符重载操作符重载操作符重载操作符/ /运算符:举例运算符:举例运算符:举例运算符:举例public class Program public int value; /public static Test operator + (Test obj1, Test obj2)/错误 / Test temp = new Test(); / temp.age = obj1.age + obj2.age; / return temp; / public static Program operator +(Program a, Program b) Program t = new Program(); t.value = a.value + b.value; return t; static void Main(string args) Program a = new Program(); Program b = new Program(); a.value = 3; b.value = 5; Program c = a + b; Console.WriteLine(c.value); Console.ReadLine(); C#C#C#4.5.2 4.5.2 重载操作符重载操作符重载操作符重载操作符/ /运算符运算符运算符运算符关于重载运算符的限制,请参照课本114页。C#C#C#作业作业作业作业全部课后习题C#C# C# 程序设计大学教程程序设计大学教程
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号