课件-面向对象_第1页
课件-面向对象_第2页
课件-面向对象_第3页
课件-面向对象_第4页
课件-面向对象_第5页
免费预览已结束,剩余125页可下载查看

下载本文档

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

文档简介

12/18/20221第4章类和方法12/18/20222利用数据抽象进行编程。数据类型两个方面:外部用户/实现者封装12/18/20223避免重复的代码保护类受到不必要的修改什么是封装12/18/20226实例实例变量/数据成员/数据字段对象=状态(实例变量)+行为(方法)

对象外部看,客户只能看到对象的行为;对象内部看,方法通过修改对象的状态,以及和其他对象的相互作用,提供了适当的行为。概念12/18/20227可视性修饰符public,privateJava和C++中,封装性由程序员确定。类的定义12/18/20228classPlayingCard{public: enumSuits{Spade,Diamond,Club,Heart}; Suitssuit(){returnsuitValue;} intrank(){returnrankValue;}private: SuitssuitValue; intrankValue;};C++12/18/20229classPlayingCard{publicintsuit(){returnsuitValue;}publicintrank(){returnrankValue;}privateintsuitValue;privateintrankValue;publicstatic

finalintSpade=1;publicstaticfinalintDiamond=2;publicstaticfinalintClub=3;publicstaticfinalintHeart=4;}Java12/18/202210类名首字母大写。数据字段privateAccessor(Getter)/Setter/Is惯例12/18/202211无可视性修饰符数据均privateSmallTalk12/18/202212先列出主要特征,次要的列在后面。私有数据字段列在后面。构造函数列在前面。类中声明次序建议-可读性12/18/202213Java,C#:方法主体直接放在类定义中。C++:分离可读性?定义和实现分离?12/18/202214接口不提供实现接口定义新类型,可以声明变量类的实例可以赋值给接口类型变量类主题的变化12/18/202215publicinterfaceStoring{voidwriteOut(Streams);voidreadFrom(Streams);};StoringstorableValue;publicclassBitImageimplementsStoring{voidwriteOut(Streams){//...}voidreadFrom(Streams){//...}};storableValue=newBitImage();接口-JavaJava为什么既有接口又有抽象类java.awt.event.ActionListener12/18/20221612/18/202217属性Delphi,VB,C#包含属性概念。类主题的变化12/18/202218publicclassPlayingCard{publicintrank{ get { returnrankValue; } set { rankValue=value; }}...privateintrankValue;}属性-C#12/18/202219向前定义多个互相引用的类(相互递归)Java全文扫描。C++向前定义类主题的变化12/18/202220classHorse;//forwarddefinitionclassBuggy{ ...

Horse*myHorse;};classHorse{ ... Buggy*myBuggy;};向前定义12/18/202221内部类(嵌套类)在一个类中定义另外一个类。(Java内部类。C++嵌套类)语义差别Java内部类被连接到外部类的具体实例上,并且允许存取其实例和方法。C++仅是命名手段,限制和内部类相关的特征可视性。类主题的变化12/18/202222类的数据字段(类属性)被一个类的所有实例共享的公共数据字段。如何对该字段初始化?类主题的变化12/18/202223每个实例都执行对公共数据字段的初始化?没有实例执行初始化任务?对象本身不对共享字段初始化。内存管理器自动将共享数据初始化为某特定值,每个实例去测试该特定值。第一个进行测试的做初始化。类的数据字段12/18/202224Java和C++使用修饰符static创建共享数据字段。4.Java:静态数据字段的初始化是在加载类时,执行静态块来完成。类的数据字段12/18/202225//某类已经创建了多少实例?classCountingClass{CountingClass(){count=count+1;//incrementcount ...}...privatestaticintcount;//sharedbyallstatic{//staticblock count=0;}}类的数据字段-Java12/18/202226由基本数据类型表示的静态数据字段可以在类的主体中进行初始化。在类外对静态数据字段进行初始化。类的数据字段-C++12/18/202227classCountingClass{public:CountingClass(){count++;...}private:staticintcount;};//globalinitializationisseparatefromclassintCountingClass::count=0;类型类名:静态成员=值类的数据字段-C++12/18/202228实现同类多个对象间的数据共享。计数器静态成员12/18/202229成员函数。不能访问非静态成员。无this构造和析构函数不能为静态成员。静态成员函数12/18/202230在JAVAAPI中有javax.swing.JOptionPane类。它包含很多类方法。Java类的设计人员为什么选择将其设计为类方法而不是实例方法main方法12/18/202231如何实例化?如何初始化?如何通过消息传递来联系?第5章消息、实例和初始化12/18/202232消息对象接收多个消息,响应不同(文理科)同一消息给多个对象,响应不同(考学结果)广播,可响应可不响应(当前课堂)12/18/202233对象间相互请求或相互协作的途径。消息12/18/202234消息-〉接收器。响应行为随接收器不同而不同。消息传递语法12/18/202235C++,C#,Java,Python,Ruby aCard.flip(); aCard.setFaceUp(true); aGame.displayCard(aCard,45,56);Pascal,Delphi,Eiffel,Oberon aCard.flip; aCard.setFaceUp(true); aGame.displayCard(aCard,45,56);Smalltalk aCardflip. aCardsetFaceUp:true. aGamedisplay:aCardatLocation:45and:56.消息传递语法12/18/202236静态:类型和变量联系在一起(Java,C++,C#,Pascal)动态:变量看作名称标识,类型和数值联系在一起。(SmatllTalk,Python)编译时刻检查?静态类型语言/动态类型语言12/18/202237面向对象静态C++,Delphipascal,Eiffel,Java面向对象动态Objective-c,Smalltalk,Dylan,Python静态类型语言/动态类型语言12/18/202238非面向对象静态Ada,Algol,C,Fortran,Haskell,ML,Modula非面向对象动态APL,Forth,Lisp,Prolog,Snobol静态类型语言/动态类型语言12/18/202239动态类型语言与静态类型语言之间的差异在于变量或数值是否具备类型这种特性。静态类型语言/动态类型语言12/18/202240焦点:高效性与灵活性争论?12/18/202241编译时作出内存分配决定。不必运行时刻重新分配。控制类型错误。静态类型语言12/18/202242Functionmax(a,b){ if(a<b) thenreturnb;returna;}动态类型语言12/18/202243Java,C++:thisEiffel:CurrentSmalltalk,object-c:self好像在使用同类的实例。伪变量12/18/202244对象自身引用this隐含指向调用成员函数的对象12/18/202245classPlayingCard{... publicvoidflip(){setFaceUp(!faceUp);}...}默认隐藏12/18/202246classPlayingCard{... publicvoidflip(){this.setFaceUp(!this.faceUp);}...}等价12/18/202247classQuitButtonextendsButtonimplementsActionListener{publicQuitButton(){...//installourselvesasalistenerforbuttonevents addActionListener(this);}...};参数传递12/18/202248Java:构造函数中,使用this区分参数和数据成员。建议12/18/202249变量声明与初始化结合变量声明与创建分离对象的创建12/18/202250C++ PlayingCard*aCard=newPlayingCard(Diamond,3);Java,C# PlayingCardaCard=newPlayingCard(Diamond,3);Smalltalk aCard<-PlayingCardnew.创建对象语法12/18/202251数组的分配和创建数组所包含对象的分配和创建对象数组的创建12/18/202252C++:结合对象使用缺省构造函数来初始化。PlayingCardcardArray[52];对象数组的创建12/18/202253Java:new仅创建数组。数组包含的对象必须独立创建。PlayingCardcardArray[]=newPlayingCard[13];for(inti=0;i<13;i++) cardArray[i]=new PlayingCard(Spade,i+1);对象数组的创建数组子类化的问题String[]stringData=newString[3]{“Larry”,”Curly”,”Moe”};Object[]objectData=stringDataobjectData[0]=newInteger(3)12/18/20225412/18/202255Java无指针?对象引用实际是存在于内部表示中的指针。指针和内存分配12/18/202256指针引用堆分配内存。指针变量生存期?堆分配的内存必须通过某种方式回收。某些语言中,指针和传统变量有区别。指针问题12/18/202257使用new创建--堆内存堆内存没有绑定在过程的入口和出口处。内存有限在程序中显式制定不再使用的对象,将其使用内存回收。

C++:delete

ObjectPascal:free内存回收12/18/2022582.垃圾回收机制(Java,C#,Smalltalk)时刻监控对象的操作,对象不再使用时,自动回收其所占内存。通常在内存将要耗尽时工作。内存回收12/18/202259付出额外代价避免释放多次;避免使用已被释放内存;避免耗尽内存。比较12/18/202260确保动态分配的内存对象都有一个指定的属主。引用计数:引用共享对象的指针的计数值。

a=newC;b=newC;a=b;垃圾回收机制12/18/202261共享资源争夺?内存12/18/202262按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的。内存分配策略12/18/202263静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间。这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求。静态存储分配12/18/202264栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的。和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存。栈式存储分配按照先进后出的原则进行分配。栈式存储分配12/18/202265静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例。堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放。堆式存储分配12/18/202266初始化新创建对象。优点:确保初始化之前不会被使用,防多次调用Java/C++:名称,返回值构造函数12/18/202267Java和C#中数据字段可以初始化为特定的数值。构造函数重载构造函数12/18/202268classComplex{//complexnumberspublicComplex(doublerv){realPart=rv;}publicdoublerealPart=0.0;//initializedataareaspublicdoubleimagPart=0.0;//tozero}构造函数12/18/202269classPlayingCard{public:PlayingCard()//defaultconstructor,//usedwhennoargumentsaregiven{suit=Diamond;rank=1;faceUp=true;}PlayingCard(Suitis)//constructorwithoneargument{suit=is;rank=1;faceUp=true;}PlayingCard(Suitis,intir)//constructorwithtwoarguments{suit=is;rank=ir;faceUp=true;}g};构造函数重载12/18/202270PlayingCardcardFive;//createsanewcardPlayingCardcardSix();//forwarddefinitionforfunctionnamedcardSixthatreturnsaPlayingCard缺省构造函数(C++)12/18/202271PlayingCardcardSeven=newPlayingCard();//JavaPlayingCard*cardEight=newPlayingCard;//C++New语法12/18/202272ClassPlayingCard{public:PlayingCard(Suitsis,intir):suit(is),rank(ir),faceUp(true){}...};C++中的初始化器12/18/202273用于对象成员初始化和派生类对基类初始化。C++中的初始化器12/18/202274缺省构造函数拷贝构造函数赋值操作符析构函数C++类规范拷贝构造函数#include

<iostream>

using

namespace

std;

class

Test

{

public:

Test(int

temp)

{

p1=temp;

}

protected:

int

p1;

};

void

main()

{

Test

a(99);

Test

b=a;

}12/18/202275就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的,在上面的代码中,我们并没有看到拷贝构造函数,同样完成了复制工作,这又是为什么呢?因为当一个类没有自定义的拷贝构造函数的时候系统会自动提供一个默认的拷贝构造函数,来完成复制工作。12/18/202276常数值初始化?Java:final可直接初始化classListofImportantPeople{public:finalintmax=100;//maximumnumberofpeople...}12/18/202277在构造函数中初始化classPlayingCard{publicPlayingCard(){suit=Diamond;rank=1;faceUp=true;}publicPlayingCard(intis,intir){suit=is;rank=ir;faceUp=true;}...publicfinalintsuit;//suitandrankarepublicfinalintrank;//immutableprivatebooleanfaceUp;//faceUpisnot}12/18/202278C++初始化classPlayingCard{public:PlayingCard():suit(Diamond),rank(1){faceUp=true;}PlayingCard(Suitsis,intir):suit(is),rank(ir){faceUp=true;}...constSuitssuit;constintrank;private:booleanfaceUp;};12/18/202279const常量,不允许改变。final仅断言相关变量不会赋予新值,并不能阻止在对象内部对变量值进行改变。如对消息的响应。Const与final区别12/18/202280final例classBox{publicvoidsetValue(intv);publicintgetValue(){returnv;}privateintv=0;}finalaBox=newBox();//canbeassignedonlyonceaBox.setValue(8);//butcanchangeaBox.setValue(12);//asoftenasyoulike12/18/202281C++在内存中开始释放对象时,自动调用。语法析构函数12/18/202282例classTrace{public://constructoranddestructorTrace(string);~Trace();private:stringtext;};Trace::Trace(stringt):text(t){cout<<"entering"<<text<<endl;}Trace::~Trace(){cout<<"exiting"<<text<<endl;}12/18/202283Java,Smalltalk中类本身是对象。那那么什么类代表了对象所属的类别,即这个类是什么类。有一个特殊的类,一般称为Class,这就是类的类。这个类所具有的行为:创建实例,返回类名称,返回类实例大小,返回类实例可识别消息列表。作为对象的类12/18/202284Objectobj=newPlayingCard();Classc=obj.getClass();System.out.println("classis"+c.getName());作为对象的类-Java12/18/202285观察12/18/202286类是对象。全对象系统12/18/202287假设现在需要一种方法:类对象PlayingCard接收后,创建两个实例。Placewhere?PlayingCard成员方法?Class成员方法?思考12/18/202288创建一个新的隐藏类:元类Smalltalk中的元类12/18/202289元类12/18/202290类MetaPlayingCard中的行为,只能被对象PlayingCard所理解,而不能被其他对象所理解。对象PlayingCard是类MetaPlayingCard的唯一实例。元类对象的产生有两种基本方式。一种是以原型(prototype)对象为基础产生新的对象。一种是以类(class)为基础产生新对象。原型的概念已经在认知心理学中被用来解释概念学习的递增特性,原型模型本身就是企图通过提供一个有代表性的对象为基础来产生各种新的对象,并由此继续产生更符合实际应用的对象。而原型-委托也是OOP中的对象抽象,代码共享机制中的一种。一个类提供了一个或者多个对象的通用性描叙。从形式化的观点看,类与类型有关,因此一个类相当于是从该类中产生的实例的集合。而这样的观点也会带来一些矛盾,比较典型的就是在继承体系下,子集(子类)对象和父集(父类)对象之间的行为相融性可能很难达到,这也就是OOP中常被引用的---子类型(subtype)不等于子类(subclass)[Budd2002]。而在一种所有皆对象的世界观背景下,在类模型基础上还诞生出了一种拥有元类(metaclass)的新对象模型。即类本身也是一种其他类的对象。以上三种根本不同的观点各自定义了三种基于类(class-based),基于原型(prototype-based)和基于元类(metaclass-based)的对象模型。而这三种对象模型也就导致了许多不同的程序设计语言(如果我们暂时把静态与动态的差别放在一边)。是的,我们经常接触的C,Java都是使用基于类的对象模型,但除此之外还有很多我们所没有接触的OOPL采用了完全不一样的对象模型,他们是在用另外一种观点诠释OOP的内涵。12/18/202295根类Object。所有类是Object的派生类。每个类是其元类的实例。每个元类是类Meta的实例。所有元类是类Class的派生类。Smalltalk元类系统12/18/202296元类为语言提供了一个方法可以将类的特定行为集成起来一个类首先并不是作为Class的实例,而是首先作为它的元类的实例,而该类又是继承自Class类通过继承,元类得到了所有Class的行为,但是它也提供了定义类的特定行为的空间。元类Smalltalk的类库及元体系结构类中描述对象的个体性质实例属性(变量)实例方法元类中描述对象的公共性质类属性(变量)类方法元类Metaclass元类是描述类的类类也是对象,每个类一定是某个元类的实例对于类A,它是元类Aclass的实例Aclass也是对象,它是谁的实例?SMALLTALK的类层次Object

┣━━Behavior┃┗━━━ClassDescription┃┣━━class┃┗━━metaclass┣━Boolean┣━Collection┃┣━━━SequenceableCollection┃┣━Bag┗━ArrayedCollection┃┗━Set┣━Array┃┗━Dictionary┣━Bitmap┃┗IdentityDictionary┗━String┃┣━Symbol┣━ComplicedMethed┣━Text┣━Maguitude┗━ByteArray┃┣━Characheter┃┣━Date┃┣━Time┃┗━Number┃┣━Float┃┗━Integer┃┣━LargeNegativeInteger┣━MethedContext┣━LargePositiveInteger┃┗Block┗━SmallInteger┃┃┃┗SelectionBlock┣━Stream┃┣━PositionableStream┃┣━ReadStream┃┗━WriteStream┃┗━UndefinedObjectSmalltalk将所有的系统成分都看作对象类层次的特点根类Object,除类Object外,其余所有的类最终都是Object的子类。每个类都是某个元类的实例。每个元类都是类Metaclass的实例类class,所有的元类最终都是class的子类反射原理元类Metaclassclass类Metaclass元类类对象元类的继承层次类的继承关系与相应的元类的继承关系是平行的如果B是A的子类,则B的元类也是A的元类的子类object是根类(无超类),而其相应的元类objectclass还有一个抽象超类class类层次与元类层次objectABclassMetaclassObjectclassAclassBclassClassclassMetaclassclassclass引入元类的优点概念上一致只用一个概念——对象就可表述系统中所有成分使类成为运行时刻一部分有助于改善程序设计环境继承的规范化类与元类的继承采用双轨制12/18/2022105反射(reflection)和内省(introspection)是指程序在运行过程中“了解”自身的能力。反射和内省12/18/2022106用于反射和内省的技术分为两大类获取理解当前计算状态的特征用于修改的特征:增加新的行为反射和内省12/18/2022107反射工具都开始于一个对象,该对象是关于一个类的动态(运行时)体现。类对象是更一般的类(称为Class类)的实例。类对象通常都包括类名称、类实例所占用内存的大小以及创建新实例的能力。类对象12/18/2022108C++typeinfoaClass=typeid(AVariable);

DelphiPascalaClass:=aVariable.ClassType;JavaClassaClass=aVariable.getClass();

SmalltalkaClass<-aVariableclass获取类对象12/18/2022109ClassparentClass=aClass.getSuperclass();//JavaparentClass<-aClasssuperclass//Smalltalk类对象操作-获取父类12/18/2022110char*name=typeinfo(aVariable).name();//C++StringinternalName=aClass.getName();//JavaStringdescriptiveName=aClass.toString();类对象操作-字符串类名称12/18/2022111如何决定多态变量是否真正包含一个指定子类的实例Child*c-dynamic_cast<Child*>(aParentPtr); if(c!=0){…}//C++if(aVariableinstanceofChild)… if(aCalss.isInstance(aVariable))…//Java类对象操作-检测对象类12/18/2022112对这种类型检测的不恰当使用是设计类结构不好的一个标志。大多数情况下,都可以通过调用改写方法来代替显式检测关于检测对象类12/18/2022113如果下一步执行的行为要依赖于多态变量所包含的特定类型:Petp=…;if(pinstanceofCat){…}elseif(pinstanceofDog){…}else{System.err.println(“Unknown”)}例12/18/2022114建立一个新方法,子类特定行为移到子类中完成,缺省行为移到父类中完成。这样做不仅代码数量减少,而且也减少了潜在的出错机会。假如要增加一个新的子类,只需要保证这个类实现正确的接口即可。Petp=…;P.newMethod();更好的解决方案12/18/2022115ObjectnewValue=aClass.newInstance();//Java类对象操作-通过类建立实例12/18/2022116ClassforName(string)ClassgetSuperClass()Constructor[]getConstructors()FieldgetField(string)Field[]getFields()Method[]getDeclaredMethods()booleanisArray()booleanisAssignableFrom(Classcls)booleanisInstance(Objectobj)booleanisInterface()ObjectnewInstance()Java中的类行为12/18/2022117Java和Smalltalk中,将方法看作是可以存取和操纵的对象。例如Java中的一个方法是Method类的一个实例,定义了如下操作:StringgetName()ClassgetDeclaringClass()IntgetModifiers()ClassgetReturntype()Class[]getParameterTypes()Objectinvoke(Objectreceiver,Object[]args)作为对象的方法12/18/2022118Method[]methods=aClass.getDeclaredMethods();System.out.println(methods[0].getName());Classc=methods[0].getReturnType();Java作为对象的方法12/18/2022119Classsc=String.class;Class[]paramTypes=newClass[1];paramTypes[0]=sc;try{ Methodmt=sc.getMethod("concat“,paramTypes); ObjectmtArgs[]={"xyz"}; Objectresult=mt.invoke("abc",mtArgs); System.out.println("resultis"+result);}catch(Exceptione){ System.out.println("Exception"+e);}Java作为对象的方法12/18/2022120Java语言的标准类库定义了一个名称为ClassLoader的类,这个类可以根据存储于文件中的信息来加载一个类。演示例程修改机制12/18/2022121面向对象语言一般支持以下原则所有对象都是某个类的实例类也是对象那么就可以回答类对象属于什么类?在Java语言中,回答相对比较简单,一个类为Class的实例,也就是自身的一个实例。元类12/18/2022122classTest{staticpublicvoidmain(String[]args){Testa=newTest();Classb=a.getClass();System.out.println("aclassis"+b);Classc=b.getClass();System.out.println("bclassis"+c);Classd=c.getClass();System.out.println("cclassis"+d);if(c==d)System.out.println(“

Theyarethesame!");}}12/18/2022123反射支持一个组件动态的加载和查询自身信息,因此反射为许多基于组件的编程工具建立了基础。反射12/18/2022124程序中的错误定位方法灵活调用对象的方法反射特征的应用得到某个对象的属性publicObjectgetProperty(Objectowner,StringfieldName)throwsException{ClassownerClass=owner.getClass();Fieldfield=ownerClass.getField(fieldName);Objectproperty=field.get(owner);returnproperty;}12/18/2022125得到某个类的静态属性publicObjectgetStaticProperty(StringclassName,StringfieldName)throwsException{ClassownerClass=Class.forName(className);Fieldfield=ownerClass.getField(fieldName);Objectproperty=field.get(ownerClass);returnproperty;}12/18/2022126执行某对象的方法publicObjectinvokeMethod(Objectowner,StringmethodName,Object[]args)throwsException{ClassownerClass=owner.getClass();Class[]argsClass=newClass[args.length];for(inti=0,j=args.length;i<j;i++){argsClass[i]=args[i].getClass();}Methodmethod=ownerClass.getMethod(methodName,argsClass);returnmethod.invoke(owner,args);}12/18/2022127执行某个类的静态

温馨提示

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

评论

0/150

提交评论