面向对象和类的设计.ppt_第1页
面向对象和类的设计.ppt_第2页
面向对象和类的设计.ppt_第3页
面向对象和类的设计.ppt_第4页
面向对象和类的设计.ppt_第5页
已阅读5页,还剩83页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

面向对象基本概念及类的设计,面向对象的基本概念,OOP以待解问题中涉及的对象为主要矛盾对象(Object)和类(Class)对象,是现实世界中的物理实体在计算机逻辑中的映射和体现。类,是同种对象的集合与抽象。(模板)消息(Message)传递一个面向对象的程序由许多对象组成,这些对象之间对象之间通过收发信息相互沟通。对于对象来说,消息就是请求执行某个过程。,面向对象的基本概念,面向对象的基本概念,对象的组成标识用以区别不同对象的唯一标志用“对象名”表达状态又称静态属性,指对象内部包含的信息用“数据成员(域)”表达行为对象的动态属性,指对象可进行的操作使用“函数成员(方法)”表达,对象和类之间,对象可以是现实生活中的一个物理对象,还可以是某一类概念实体的实例。例如:一辆汽车、一个人、一本书,乃至一种语言、一个图形、一种管理方式,都可以作为一个对象。类是一组具有相同数据结构和相同操作的对象的集合。类是对一系列具有相同性质的对象的抽象,是对对象共同特征的描述。比如每一辆汽车是一个对象的话,所有的汽车可以作为一个模板,我们就定义汽车这个类。可以使用类的定义实例化对象,这表示创建该类的一个实例。从类定义中产生对象,必须有建立实例的操作。,结构化程序设计回顾,自顶向下的设计方法:,结构化程序设计回顾,面向过程程序中函数和数据的关系:,程序=数据结构+算法,面向对象程序设计(OOP),面向对象程序设计技术汲取了结构化程序设计中好的思想,并将这些思想与一些新的、强大的理念相结合,从而给你的程序设计工作提供了一种全新的方法。通常,在面向对象的程序设计风格中,你会将一个问题分解为一些相互关联的子集,每个子集内部都包含了相关的数据和函数。同时,你会以某种方式将这些子集分为不同等级,而一个对象就是已定义的某个类型的变量。当你定义了一个对象,你就隐含的创建了一个新的数据类型。,面向对象程序设计(OOP),面向对象程序设计中的数据和函数的组织结构:,实例1:电灯,数据(状态):亮/暗方法(动作):开、关用户通过方法改变电灯内部的数据,实例2.汽车,实例3:八皇后问题,八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。,实例3:八皇后问题,结构化编程实现面向对象编程实现,面向对象程序设计的特点,抽象性抽象(abstraction):去掉研究问题中次要的部分,仅仅抽取主要的、本质的部分进行研究的方法。过程抽象:面向过程方法使用数据抽象:面向对象方法使用抽象数据类型(ADT),面向对象程序设计的特点,封装性封装(encapsulation):利用ADT将数据和基于数据的操作密封在一起,系统的其它对象只能通过界面与其交互。封装机制将数据和代码捆绑到一起,避免了外界的干扰和不确定性。封装的优点提高了系统灵活性提高了系统安全性实例:银行账户,面向对象程序设计的特点,继承性(具体化)继承(Inheritance)是可以让某个类型的对象获得另一个类型的对象的属性的方法。允许程序设计人员在设计新类时,只考虑与已有的父类所不同的部分,从而继承父类的内容为自己的组成部分可在子类中重写方法的实现,改变父类中不适合子类的行为提高了代码复用率,能使开发者的大部分精力用于系统特殊的设计,便于软件的演进和增量式扩充。C#只支持单继承,但支持多重接口的继承实现继承支持按级分类的概念。继承很好的支持代码的重用性(reusability)。,面向对象程序设计的特点,多态性多态(Polymorphism):多态的意思是事物具有不同形式的能力。例如,对不同的实例,某个操作可能会有不同的行为。这个行为依赖于所要操作数据的类型。多态机制使具有不同内部结构的对象可以共享相同的外部接口。多态的实现重载(overload)覆盖(override)实例:cd/dvd播放,OOP概念总结,任何事物都是一个对象通过相互联系的对象请求其他对象执行一定的行为来完成计算。对象之间通过发送和接收消息来进行通信。每个对象都有自己的存储空间,用来存储其它对象每个对象都是一个类的实例。类用来代表一组相似的对象及其相关的行为,即同一个类的多个对象能执行相同行为类可以组织成一个单根树状组织,成为继承层次,每个类事例的存储空间和行为自动被其派生类使用,从一个实例出发:图书馆管理系统,功能需求:一个图书馆藏有图书和期刊杂志两大类书籍,每种图书/杂志可以有多册。图书馆可以维护(注册、更新和删除)图书资料。图书管理员在系统的支持下,负责与借书者打交道。借书者可以预约目前借不到的书或杂志。所有人员都可以浏览图书馆的图书信息和各种告示。,从一个实例出发:图书馆管理系统,非功能需求系统能够在所有流行的技术环境下运行,有一个良好的交互界面。系统应该具有良好的可扩展性。取名:LibM,图书馆系统的用例视图,查询图书,查询系统信息,系统管理员,借书者,一般浏览者,普通管理员,借书,还书,续借,预约,查询账户,注册借书者,更新借书者,注销借书者,更新图书,删除图书,录入书目,更新书目,删除书目,管理借书者,管理书目,管理图书,录入图书,建立侯选类,给出非形式化描述:借书者通过管理员可以借、还、续借图书馆的图书;图书馆的管理员维护借书者、图书目录和图书信息;借书者还可以预约没有归还的图书或新书,也可以取消预约,浏览和查询个人和图书信息;图书可以有多本,借书者不能借超过规定数目的图书;如果借书者有超期的图书或罚金额度超过2元,则不能借书。,借书者,图书,图书目录,设计LibM的类,类的对象应该管理自己的数据并承担其责任借书者属性:谁?借了哪些书?罚金多少?功能:借书、续借、还、预约、交罚款。图书(对应实际的书)属性:书名、作者、出借日期功能:被借、被归还图书目录(对应管理的书)属性:哪本书?可借数?预约数?功能:借、归还、预约,类的声明,类的修饰符class类名/类成员的声明/嵌套类的声明,类的成员,类自身声明的+基类中继承的成员分类常量变量构造函数和析构函数,对类的实例进行初始化和销毁成员方法,复杂执行类中的计算和其他操作属性,定义类中的值,并对他们进行读写事件,用于通知其他类发生了一件什么事情索引指示器,允许象使用数组一样为类添加路径列表操作符,定义类中特有的操作,定义LibM的类,这些类无法使用!,访问修饰符,类访问修饰符:publicprivateprotectedinternal,成员访问修饰符:publicprivateprotectedinternalinternalprotected,默认,默认,学会学习:internal的含义?,访问修饰符总结,public(可以修饰类)同一程序集中的任何其他代码或引用该程序集的其他程序集都可以访问该类型或成员。private(成员的默认访问修饰符)只有同一类或结构中的代码可以访问该类型或成员。protected只有同一类或结构或者派生类中的代码可以访问该类型或成员。internal(可以修饰类,类的默认修饰符)同一程序集中的任何代码都可以访问该类型或成员,但其他程序集中的代码不可以。protectedinternal同一程序集中的任何代码或其他程序集中的任何派生类都可以访问该类型或成员。嵌套类可以访问外部类的方法、属性、字段而不管访问修饰符的限制,而外部类只能够访问修饰符为public、internal嵌套类的字段、方法、属性。示例,访问修饰符设置规则,仅仅暴露需要暴露的。尽量用更小可见性的类来实现公共接口可见性越小,以后更新时,整个系统的变化就越少。能访问一段代码的地方越少,以后进行修改时,要修改的地方就越少。,使用LibM的类,如何确定归还书所对应的图书目录呢?,思路首先,必须知道要归还的图书。其次,根据图书确定图书目录。解决方法:在某个类中提供根据图书获取图书目录的方法。哪个类?图书、图书目录、借书者?困境:把获取图书目录的任务交给图书目录?,确定图书所对应的图书目录,静态方法!,静态成员和实例成员,类的静态成员是类的一部分,但它独立于任何一个单独的类实例,在类的实例被创建前就可被引用,所有的类实例共享该静态成员。类名.静态成员名非静态(实例)数据成员存储于特定的类实例绑定,必须在类实例被创建出来后才具有存储空间并对其进行操作。类名id=new类名();id.实例成员,静态成员举例,成员的初始化,静态类,所有成员都是静态成员的类。无法创建静态类的实例。用途:控制类、工具类。比较:Math类intr=Math.Sqrt(20);/静态方法Random类Randomran=newRandom();intr=ran.Next(20);/实例方法,数据成员的初始化,数据成员可在声明时被初始化为某常量,或引用其他的静态成员不能引用类的非静态变量成员来进行其他变量的初始化,publicclassClass4privateinta;protectedintb=111;publicstaticintc=120;publicstaticintd=c+12;publicstaticinte=b+10;/错误?publicintf=b+1;/错误?。,Employee中的静态/实例成员,classEmployeepublicstringFirstName;publicstringLastName;publicdoubleSalary;/静态,从所有该类对象中选择一个改变其状态publicstaticvoidIncreaseSalaryS(Employeee,doublenum)e.Salary+=num;/(实例)方法,对调用该方法的对象起作用publicvoidIncreaseSalaryNS(doublenum)Salary+=num;,classProgramstaticvoidMain()Employeee1=newEmployee();Employeee2;/Error!e2此时为空引用/e2.FirstName=Inigo;/e2.LastName=Montaya;/e2.Salary=1000;e1.FirstName=Inigo;e1.LastName=Montaya;e1.Salary=1000;Employee.IncreaseSalaryS(e1,500);e1.IncreaseSalaryNS(500);,矩阵乘法的静态和非静态实现,现在,你知道为什么Main必须是静态方法了吗?,罚款功能的设计,什么时候确定罚款?还书的时候。谁来负责确定罚款?图书目录实体书借阅者罚款的规则?每超期1天罚款1分。,最佳“人选”,常量,成员常量的声明const,attributesconstdatatypeidentifier;,newpublicprotectedinternalprivate,classApublicconstdoublex=1.0;privateconstinty=2;publicconststringpre=“good”;,Const成员本质上是static的,一定是在声明的同时被初始化,其值在编译阶段已确定,罚款功能的实现,构造函数,前面设计的一个缺陷:直接把对象内部的成员变量暴露在外。目标:在创建对象的同时可以设置成员变量的取值。实现:构造函数每个类都必须有构造函数,系统自动提供默认构造函数。创建对象时一定会调用,而且调用自动进行。若存在多个构造函数,则系统按照参数匹配算法选择最匹配函数构造函数的三个特性:与类名同名不返回任何值不能显式调用,classEmployeestringFirstName;stringLastName;doubleSalary;publicEmployee()FirstName=LastName=N/A;Salary=0;publicEmployee(stringfirstName,stringlastName)FirstName=firstName;LastName=lastName;Salary=1000;publicEmployee(stringfirstName,stringlastName,doublesalary)FirstName=firstName;LastName=lastName;Salary=salary;publicstaticvoidIncreaseSalaryS(Employeee,doublenum)e.Salary+=num;publicvoidIncreaseSalaryNS(doublenum)Salary+=num;publicvoidPrintInfo()Console.WriteLine(01:2,FirstName,LastName,Salary);,重载构造函数,若不提供,则系统提供默认无参数的构造函数,classProgramstaticvoidMain()Employeee1=newEmployee();Employeee2=newEmployee(John,Smith,3000);Employeee3=newEmployee(Jack,Johns);e1.PrintInfo();e2.PrintInfo();e3.PrintInfo();/加薪Console.WriteLine(加薪后。);e2.IncreaseSalaryNS(1000);Employee.IncreaseSalaryS(e3,1500);e2.PrintInfo();e3.PrintInfo();Console.Read();,构造函数注意点,构造函数一般不会被显式调用,而由new操作触发,将实例化好的对象返回给new的左值构造函数的特征构造函数允许重载,若未定义,系统会提供默认构造函数一般来说,构造函数应为public,但也存在特殊的情况,高级内容:单件模式,问题:局域网里只有一台打印机,很多人都要打印,因此必须有一个打印机精灵(PrintDeamon)程序来负责排队,怎么保证系统内只有一个实例呢?目的:保证一个类仅有一个实例,并提供一个访问它的全局访问点。解决方案:单件模式,使用私有、静态构造函数,publicclassSingletonstaticSingletoninstance=null;Singleton()/必须,否则默认构造函数为publicpublicstaticSingletonGetInstance()if(instance=null)instance=newSingleton();returninstance;,classProgrampublicstaticvoidMain()/Singletons=newSingleton();Singletons1=Singleton.GetInstance();Singletons2=Singleton.GetInstance();if(s1=s2)Console.WriteLine(Equal!);Console.Read();,this保留字,限于构造函数、析构函数和类的实例方法中使用类的构造函数中出现,作为引用类型,表示对正在构造的对象本身的引用类的方法中出现作为引用类型,表示对调用该方法的对象的引用,this示例(1),usingSystem;classApublicintx;privatestaticstr=“Helloworld”;publicvoidfunc()x=5;Console.WriteLine(“Thevalueofxis:0”,x);Console.WriteLine(“Thevalueofthis.xis:0”,this.x);Console.WriteLine(this.str);/Error!,为何不能使用this来引用静态变量?,This举例(2),UsingSystem;publicclassPointpublicintx,y;/用this来避免歧义publicvoidSetPoint(intx,inty)this.x=x;this.y=y;,注意:C#内部,this被定义为一个常量,不能使用this+,this-等表达式,但可将this作为返回值使用,This举例(3),classEmployeestringFirstName;stringLastName;doubleSalary;publicEmployee(stringFirstName,stringLastName,doubleSalary)this.FirstName=FirstName;this.LastName=LastName;this.Salary=Salary;publicEmployee(stringFirstName,stringLastName):this(FirstName,LastName,1000)publicstaticvoidIncreaseSalaryS(Employeee,doublenum)e.Salary+=num;publicvoidIncreaseSalaryNS(doublenum)IncreaseSalaryS(this,num);publicvoidPrintInfo()Console.WriteLine(01:2,FirstName,LastName,Salary);,This的典型用法1.用来引用实例成员,避免歧义2.在构造函数中用this()调用另一个构造函数,避免代码重复3.表示对象实例本身的引用,将自己作为参数传递出去,classProgramstaticvoidMain()Employeee2=newEmployee(John,Smith,3000);Employeee3=newEmployee(Jack,Johns);e2.PrintInfo();e3.PrintInfo();/加薪Console.WriteLine(加薪。);e2.IncreaseSalaryNS(1000);Employee.IncreaseSalaryS(e3,1500);e2.PrintInfo();e3.PrintInfo();Console.Read();,析构函数(终结器),类的实例超出作用域范围时,释放它所占用的资源,由系统负责调用形式:类名(),不接受任何参数,也不返回任何值,否则报错析构函数不能被继承和显式调用。由于GC,大多数类不用显式定义析构函数,但若在类中申请了独占资源,最好保证在对象结束前释放掉当存在类继承时,基类/子类的析构函数的调用顺序与构造函数的调用顺序正好相反构造函数:先基类,后子类析构函数:先子类,后基类,回到书本。,P126可用静态字段提供计数、索引等操作p135,作业4,定义一个网络用户类,要处理的信息有:用户ID、用户密码、email地址,在建立类的实例时,把以上三个信息作为构造函数的参数输入,其中用户ID和用户密码是必须的,缺省的email地址是用户ID加上“”(考察:构造函数的重载)统计开学报到的学生数,要求定义一个学生类,由其中的数据成员来跟踪已报到的学生数(使用静态成员)总结你对访问修饰符的不同组合、静态/非静态成员的区别,LibM的改进版本,封装的第二阶段:数据隐藏应用以下技术:恰当的访问限定符成员常量和成员初始化构造函数、析构函数静态成员,静态类,使用getter/Setter函数对对类内部的私有数据进行操作优点:实现了数据隐藏和安全访问对读/写可进行灵活的控制缺点:代码比较繁琐可读性较差,影响到可编程性有没有两全其美的方法呢?,属性,类的属性成员,用来描述、表达对象的一些特征属性,是对变量成员的一种扩展C#中,属性使用专门的访问函数对属性值进行读写操作,提供了比变量成员更为灵活的应用机制使用时形式上像数据成员(虚字段),本质上是方法格式修饰符数据类型属性名访问函数体,访问函数get/set,get用于向外部返回属性成员的值,不带参数修饰符get语句或语句块Set用于处理类外部的写入值,是一个带有简单值类型参数的方法修饰符set语句或语句块特殊关键字value-set函数的隐式参数示例代码:用属性改写Box(p150),属性的常见用法,可以在get和set操作中根据需要添加验证代码:读取某字段时判断有没有权限设置某字段时判断新值是否合法根据系统的需求,只提供get/set访问器,即只读/只写属性,publicclassEmployeeprivatestringname;privatelongidcard;privatedoublesalary;privatedoubleincrease;publicvoidPrint()Console.WriteLine(姓名:0,name);Console.WriteLine(身份证号:0,idcard);Console.WriteLine(基本工资:0,C,salary);Console.WriteLine(增加工资:0:C,increase);publicvoidRaise(doublepercent)increase=percent*salary;publicdoubleSalarygetreturnsalary;setif(value=0)Console.Write(Itsnotavalidsalary!);elsesalary=value;,publicstringNamegetreturnname;setname=value;publiclongIDgetreturnidcard;/为保证唯一,一般不修改publicdoubleIncreasegetreturnincrease;,员工的工资必须为非负数,对一般用户而言,工资的增长率应该是只读的,使用属性,如果只提供get访问器,那么这个属性是只读的。如果只提供set访问器,那么这个属性是只写的。建议:将所有字段都定义为private。如果字段需要公开,请使用属性将其公开,属性使用的另一例子,示例MyTime,定义类,对象的状态,对象的行为,字段,属性,方法,C#支持的第三种注释方式,提供标准的方式对函数的功能、参数、返回值进行说明,类成员的访问属性,上述MyTime类中,所有成员的访问属性都是public.这样,我们想获得小时数、分钟数、秒数比较方便,类成员的访问属性,但也带来了不安全的因素,因为public属性既可以让任何人来读,也可以让任何人来改写。,类成员的访问属性,那么,我们将类的字段的访问属性定义为private.,这样,在类的外部(类的使用者)就无法修改这个字段的值,因为根本看不到。当然,也没有办法取它的值了。,有没有一种途径,它可以让使用者像使用公共的字段一样方便,又能让设计者能够进行安全地检查?,使用属性,我们可以使用属性来解决这个问题。属性,从外部(类的使用者)来看,类似于类的字段。从内部(类的作者)来看,类似于类的方法。,get访问器,set访问器,MyTimepreTime=newMyTime(19,34,56);MyTimenowTime=newMyTime(21,45,26);/这句错误,因为hour为私有域,不能在MyTime类外被访问intelapsedHour=nowTime.hour-preTime.hour;/error!intelapsedHour=nowTime.Hour-preTime.Hour;/Correct!nowTime.Minute=106;nowTime.Second+=20;,先调用Second属性的一次Get操作,再调用一次Set操作,调用set操作,但由于if条件不满足,minute不变,属性成员vs.变量成员,变量成员本质上就是变量,而属性成员更大程度上是函数成员的一种,只是操作时形式比较类似变量访问属性成员在访问修饰符的基础上通过get/set函数提供对属性的更为灵活、安全的访问控制,可为(私有)的变量成员多一层逻辑保护,而变量成员只能通过访问修饰符提供基本的数据隐藏功能属性成员可通过只公开get/set,实现成员的只读/只写,而变量要么全部可见要么全不可见,自动属性,classAintlength;publicintLengthgetreturnlength;setlength=value;,classApublicintLengthget;set;,等价,1.自动属性不需要创建私有成员2.如果除了简单得读取和赋值还要做起他的操作,必须单独创建访问器,索引器,索引器是C#的简单组件索引器通常在包含元素集合的类中定义为数组创建索引器后,可以通过从类对象指定索引来直接访问数组元素可以用索引数组的方式索引对象可以像访问数组一样访问类的成员,而不用将内部的细节暴露给用户,classIndexerExamplepublicstringstringList=newstring10;publicstringthisintindexgetreturnstringListindex;setstringListindex=value.ToString();,classTeststaticvoidMain()IndexerExampleindexTest=newIndexerExample();indexTest.stringList1=Sam;indexTest2=Tom;System.Console.WriteLine(“indexTest1是0nindexTest2是1,indexTest1,indexTest2);,定义索引器的规则,必须指定至少一个索引器参数应当为索引器参数赋值示例:使用索引给学生打分,索引器与数组的比较4-1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论