05面向对象类、方法、消息、实例_第1页
05面向对象类、方法、消息、实例_第2页
05面向对象类、方法、消息、实例_第3页
05面向对象类、方法、消息、实例_第4页
05面向对象类、方法、消息、实例_第5页
已阅读5页,还剩92页未读 继续免费阅读

下载本文档

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

文档简介

1、类和方法 2021-6-7 n 利用数据抽象进行编程。 n 数据类型两个方面:外部用户/实现者 6/7/20212 6/7/20213 n 避免重复的代码 n 保护类受到不必要的修改 n 实例 n 实例变量/数据成员/数据字段 n 对象=状态(实例变量)+行为(方法) 对象外部看,客户只能看到对象的行为; 对象内部看,方法通过修改对象的状 态,以及和其他对象的相互作用,提 供了适当的行为。 6/7/20216 n 可视性修饰符public,private n Java和C+中,封装性由程序员确定。 6/7/20217 class PlayingCard public: enum Suits S

2、pade, Diamond, Club, Heart; Suits suit () return suitValue; int rank () return rankValue; private: Suits suitValue; int rankValue; ; 6/7/20218 class PlayingCard public int suit () return suitValue; public int rank () return rankValue; private int suitValue; private int rankValue; public static final

3、 int Spade = 1; public static final int Diamond = 2; public static final int Club = 3; public static final int Heart = 4; 6/7/20219 n 类名首字母大写。 n 数据字段private n Accessor(Getter)/Setter/Is 6/7/202110 n 无可视性修饰符 n 数据均private 6/7/202111 n 先列出主要特征,次要的列在后面。 n 私有数据字段列在后面。 n 构造函数列在前面。 6/7/202112 n Java,C#:方法主

4、体直接放在类定义中。 n C+:分离 n 可读性? 6/7/202113 n 接口 1.不提供实现 2.接口定义新类型,可以声明变量 3.类的实例可以赋值给接口类型变量 6/7/202114 public interface Storing void writeOut (Stream s); void readFrom (Stream s); ; Storing storableValue; public class BitImage implements Storing void writeOut (Stream s) / . void readFrom (Stream s) / . ; s

5、torableValue = new BitImage(); 6/7/202115 n 属性 1.Delphi,VB,C#包含属性概念。 6/7/202116 public class PlayingCard public int rank get return rankValue; set rankValue = value; . private int rankValue; 6/7/202117 n 类的数据字段 n (类属性) 1.被一个类的所有实例共享的公共数据 字段。 2.如何对该字段初始化? 6/7/202118 1.每个实例都执行对公共数据字段的初 始化? 2.没有实例执行初始化

6、任务? 3.对象本身不对共享字段初始化。内存 管理器自动将共享数据初始化为某特 定值,每个实例去测试该特定值。第 一个进行测试的做初始化。 6/7/202119 n Java和C+使用修饰符static创建共享 数据字段。 4.Java:静态数据字段的初始化是在加载 类时,执行静态块来完成。 6/7/202120 /某类已经创建了多少实例? class CountingClass CountingClass () count = count + 1; / increment count . . private static int count; / shared by all static /

7、 static block count = 0; 6/7/202121 1.由基本数据类型表示的静态数据字段 可以在类的主体中进行初始化。 2.在类外对静态数据字段进行初始化。 6/7/202122 class CountingClass public: CountingClass () count+; . private: static int count; ; / global initialization is separate from class int CountingClass:count = 0; 类型 类名:静态成员=值 6/7/202123 n 实现同类多个对象间的数据共享

8、。 n 计数器 6/7/202124 n 成员函数。不能访问非静态成员。 n 无this n 构造和析构函数不能为静态成员。 6/7/202125 山东大学计算机学院26 Java同时也包含无对象(objectless)变量及无对象方法, 称为类变量和类方法 实际上,通过使用Java的这些无对象特性,可以编写一 个几乎完全非面向对象地程序。 类变量的典型使用方式是定义常量。 这样的常量不仅被该类的所有对象共享,而且通常被声 明为公共变量,以供给该程序中所有的对象和类使用 除了用来定义常量以外,类变量也可以用来使得某类所 有的实例(对象)共享一份数据 山东大学计算机学院27 类方法可以被视为可独

9、立于某类的所有对象而进行调用 的方法,而非传递给该类的对象的消息。 类方法能在不引用Math对象的情况下,被Java代码中 的任何主体存取和执行。 山东大学计算机学院28 当定义类并且确定该类应当包含何种方法,是类方法还是 实例方法时,通常并不是一目了然的。 比如,假设要定义一个Set类(不同于java.util.Set接口), 其对象行为类似于数学概念上的(有限、无序)整数集合。 对于这样一个集合很自然的操作便是与另一个Set对象求 交集。对于该Set类,这样的操作有如下(至少)两个版 本的声明方式: Public Set intersect (Set otherSet) Public st

10、atic Set intersect (Set firstSet, Set secondSet) 哪个版本更好呢? 山东大学计算机学院29 将大段的代码分解为方法,并且将代码段替代为方法调用, 可以允许编程人员在更高的层次上来考虑计算过程。 这样,方法就提高了代码的可读性。这种将代码分解为方 法的过程成为功能分解(functional decomposition) 将代码分解为设计良好的方法不仅能提高代码的可读性, 还能提高代码的可重用性 一个设计良好的方法可以成为编程人员的另一种工具,让 编程人员可以在需要完成特定目标的时候随时使用 山东大学计算机学院30 什么时候需要把一个方法分解为另外的

11、方法呢?一个最简 单的经验法则就是,如果方法体不能同时在电脑屏幕中完 全显示,它可能就太长了,需要将一些工作转交给其他方 法。 当有代码冗余的时候也需要考虑进行分解。也就是说,如 果某程序有两个部分的指令执行序列完全一致,那么更好 的做法就是,将这个一样的代码移至一个单独的方法中, 并将原来的代码替换为一个方法调用。 山东大学计算机学院31 对于删除Java中构造函数里的代码冗余还有一个特殊的称 为构造函:函数链(constructor chaining)的机制。 这是关于一个构造函数通过“this”调用另一个构造函数 的机制。比如,考虑如下具有两个构造函数的类。它假设 一个家庭总是有一位父亲

12、、一位母亲、零个或者多个孩子。 山东大学计算机学院32 Public class Family Public Family (Person father, Person mother, Person children) Code ) Public Family (Person father, Person mother) This (father, mother, new Person 0 ) ; ) . .other methods . . ) 第二个构造函数调用了第一个构造函数,因此它仅仅是一个允许用户 不需要创建一个空的数组,来表明某家庭(还)没有孩子的便捷构造 函数。 山东大学计算机学

13、院33 方法的一个重要属性就是它们应该尽可能地独立。 比如,如果某方法使用了实例变量或者调用了私有方法, 那么该方法就仅仅在该类的上下文中有用。 与之相反,如果该方法,通过参数得到所有数据,并且根 据这些参数来实现方法调用的话,那么该方法就可以随意 移动到任何类中,而这给了代码组织更大的灵活性。 山东大学计算机学院34 方法的另一个重要属性是,它们只实现一个功能。当您建 立或者试图建立一个方法时,试想一下您是否可以在不使 用“和”这个词的情况下,用一个句子完全描述该方法做 了些什么。如果不能完全描述的话,该方法很可能需要被 分为两个或者多个方法。 指导原则 一个方法应该只实现一个任务并且要很好

14、地完成该任务。 该指导原则称为组合方法 遵循该指导原则的方法被称为具有很强的“功能内聚”(functional cohesion) n 下面我们开始谈谈: n 如何实例化?如何初始化?如何通过消息传 递来联系? 6/7/202135 n 对象间相互请求或相互协作的途径。 6/7/202136 n 消息-接收器。 n 响应行为随接收器不同而不同。 6/7/202137 C+, C#, Java, Python, Ruby aCard.flip (); aCard.setFaceUp(true); aGame.displayCard(aCard, 45, 56); Pascal, Delphi,

15、Eiffel, Oberon aCard.flip; aCard.setFaceUp(true); aGame.displayCard(aCard, 45, 56); Smalltalk aCard flip. aCard setFaceUp: true. aGame display: aCard atLocation: 45 and: 56. 6/7/202138 n 静态:类型和变量联系在一起 (Java,C+,C#,Pascal) n 动态:变量看作名称标识,类型和数 值联系在一起。(SmatllTalk,Python) n 编译时刻检查? 6/7/202139 n 面向对象静态 n C

16、+,Delphi pascal,Eiffel,Java n 面向对象动态 n Objective-c,Smalltalk,Dylan,Python 6/7/202140 n 非面向对象静态 n Ada,Algol,C,Fortran,Haskell,ML,Mo dula n 非面向对象动态 n APL,Forth,Lisp,Prolog,Snobol 6/7/202141 n 动态类型语言与静态类型语言之间的 差异在于变量或数值是否具备类型这 种特性。 6/7/202142 n 焦点:高效性与灵活性 6/7/202143 n 编译时作出内存分配决定。不必运行 时刻重新分配。 n 控制类型错误。

17、 6/7/202144 Function max(a,b) if (ab) then return b; return a; 6/7/202145 n Java,C+:this n Eiffel:Current n Smalltalk,object-c:self n 好像在使用同类的实例。 6/7/202146 n this隐含指向调用成员函数的对象 class QuitButton extends Button implements ActionListener public QuitButton () . / install ourselves as a listener for butt

18、on events addActionListener(this); . ; 6/7/202147 6/7/202148 C+ PlayingCard * aCard = new PlayingCard(Diamond, 3); Java, C# PlayingCard aCard = new PlayingCard(Diamond, 3); Smalltalk aCard - PlayingCard new. 1.数组的分配和创建 2.数组所包含对象的分配和创建 6/7/202149 n Java:new仅创建数组。数组包含的对 象必须独立创建。 PlayingCard cardArray

19、= new PlayingCard13; for (int i = 0; i 13; i+) cardArrayi = new PlayingCard(Spade,i+1); 6/7/202150 n 数组子类化的问题 nString stringData=new String3“Larry”,”Curly”,”Moe”; nObject objectData=stringData nobjectData0=new Integer(3) 6/7/202151 n Java无指针? n 对象引用实际是存在于内部表示中的 指针。 6/7/202152 n 使用new创建-堆内存 n 堆内存没有绑定

20、在过程的入口和出口 处 n 内存有限 1.在程序中显式制定不再使用的对象, 将其使用内存回收。 C+:delete Object Pascal:free 6/7/202153 2.垃圾回收机制(Java,C#,Smalltalk) n 时刻监控对象的操作,对象不再使用 时,自动回收其所占内存。 n 通常在内存将要耗尽时工作。 6/7/202154 1.付出额外代价 2.避免释放多次;避免使用已被释放内 存;避免耗尽内存。 6/7/202155 1.确保动态分配的内存对象都有一个指 定的属主。 2.引用计数:引用共享对象的指针的计 数值。 a=new C;b=new C;a=b; 6/7/202

21、156 n按照编译原理的观点,程序运行时 的内存分配有三种策略,分别是静态 的,栈式的,和堆式的。 6/7/202157 n 静态存储分配是指在编译时就能确定每个数据目标 在运行时刻的存储空间需求,因而在编译时就可以给 他们分配固定的内存空间。 n 这种分配策略要求程序代码中不允许有可变数据结 构(比如可变数组)的存在,也不允许有嵌套或者递归 的结构出现,因为它们都会导致编译程序无法计算准 确的存储空间需求。 6/7/202158 n 栈式存储分配也可称为动态存储分配,是由一个类似 于堆栈的运行栈来实现的。 n 和静态存储分配相反,在栈式存储方案中,程序对数据 区的需求在编译时是完全未知的,只

22、有到运行的时候 才能够知道,但是规定在运行中进入一个程序模块时, 必须知道该程序模块所需的数据区大小才能够为其 分配内存。 n 栈式存储分配按照先进后出的原则进行分配。 6/7/202159 n 静态存储分配要求在编译时能知道所有变量的存储 要求,栈式存储分配要求在过程的入口处必须知道所 有的存储要求,而堆式存储分配则专门负责在编译时 或运行时模块入口处都无法确定存储要求的数据结 构的内存分配,比如可变长度串和对象实例。 n 堆由大片的可利用块或空闲块组成,堆中的内存可以 按照任意顺序分配和释放。 6/7/202160 n 初始化新创建对象。 n 优点:确保初始化之前不会被使用,防多次 调用

23、n Java/C+:名称,返回值 6/7/202161 n Java和C#中数据字段可以初始化为特 定的数值。 n 构造函数重载 6/7/202162 class Complex / complex numbers public Complex (double rv) realPart = rv; public double realPart = 0.0; / initialize data areas public double imagPart = 0.0; / to zero 6/7/202163 class PlayingCard public: PlayingCard ( ) / d

24、efault constructor, / used when no arguments are given suit = Diamond; rank = 1; faceUp = true; PlayingCard (Suit is) / constructor with one argument suit = is; rank = 1; faceUp = true; PlayingCard (Suit is, int ir) / constructor with two arguments suit = is; rank = ir; faceUp = true; g ; 6/7/202164

25、 PlayingCard cardFive; / creates a new card PlayingCard cardSix(); / forward definition for function named cardSix that returns a PlayingCard 6/7/202165 PlayingCard cardSeven = new PlayingCard(); / Java PlayingCard *cardEight = new PlayingCard; / C+ 6/7/202166 Class PlayingCard public: PlayingCard (

26、Suits is, int ir) : suit(is), rank(ir), faceUp(true) . ; 6/7/202167 n 用于对象成员初始化和派生类对基类 初始化。 6/7/202168 1.缺省构造函数 2.拷贝构造函数 3.赋值操作符 4.析构函数 6/7/202169 #include using namespace std; class Test public: Test(int temp) p1=temp; protected: int p1; ; void main() Test a(99); Test b=a; 6/7/202170 当一个类没有自定义的拷贝构造

27、 函数的时候系统会自动提供一 个默认的拷贝构造函数,来完 成复制工作 Java:final 可直接初始化 class ListofImportantPeople public: final int max = 100; / maximum number of people . 6/7/202171 class PlayingCard public PlayingCard ( ) suit = Diamond; rank = 1; faceUp = true; public PlayingCard ( int is, int ir) suit = is; rank = ir; faceUp =

28、true; . public final int suit; / suit and rank are public final int rank; / immutable private boolean faceUp; / faceUp is not 6/7/202172 class PlayingCard public: PlayingCard () : suit(Diamond), rank(1) faceUp = true; PlayingCard (Suits is, int ir) : suit(is), rank(ir) faceUp = true; . const Suits s

29、uit; const int rank; private: boolean faceUp; ; 6/7/202173 1.const常量,不允许改变。 2.final仅断言相关变量不会赋予新值, 并不能阻止在对象内部对变量值进行 改变。如对消息的响应。 6/7/202174 class Box public void setValue (int v); public int getValue () return v; private int v = 0; final aBox = new Box(); / can be assigned only once aBox.setValue(8);

30、/ but can change aBox.setValue(12); / as often as you like 6/7/202175 n C+ n 在内存中开始释放对象时,自动调用。 n 语法 6/7/202176 class Trace public: / constructor and destructor Trace (string); Trace (); private: string text; ; Trace:Trace (string t) : text(t) cout entering text endl; Trace:Trace () cout exiting text

31、 endl; 6/7/202177 1.Java,Smalltalk中类本身是对象。那么 什么类代表了对象所属的类别,即这 个类是什么类。有一个特殊的类,一 般称为Class,这就是类的类。 2.这个类所具有的行为:创建实例,返 回类名称,返回类实例大小,返回类 实例可识别消息列表。 6/7/202178 Object obj = new PlayingCard(); Class c = obj.getClass(); System.out.println(class is + c.getName(); 6/7/202179 类是对象。 6/7/202180 n 反射(reflection)和

32、内省(introspection) 是指程序在运行过程中“了解”自身 的能力。 6/7/202181 n用于反射和内省的技术分为两大类 n获取理解当前计算状态的特征 n用于修改的特征:增加新的行为 n 反射工具都开始于一个对象,该对象 是关于一个类的动态(运行时)体现。 n 类对象是更一般的类(称为Class类) 的实例。 n 类对象通常都包括类名称、类实例所 占用内存的大小以及创建新实例的能 力。 6/7/202182 n C+ typeinfo aClass = typeid(AVariable); n n Delphi Pascal aClass := aVariable.ClassTy

33、pe; n Java Class aClass = aVariable.getClass(); n n Smalltalk aClass - aVariable class 6/7/202183 n Class parentClass = aClass.getSuperclass(); / Java n parentClass - aClass superclass /Smalltalk 6/7/202184 n char * name = typeinfo(aVariable).name(); / C+ n String internalName=aClass.getName();/Java

34、 String descriptiveName=aClass.toString(); 6/7/202185 n 如何决定多态变量是否真正包含一个指定子类的 实例 n Child *c-dynamic_cast(aParentPtr); if (c!=0) /C+ n if (aVariable instanceof Child) if (aCalss.isInstance(aVariable) /Java 6/7/202186 n 如果下一步执行的行为要依赖于多态 变量所包含的特定类型: Pet p=; if(p instanceof Cat) else if(p instanceof Dog

35、) else System.err.println(“Unknown”) 6/7/202187 n 建立一个新方法,子类特定行为移到 子类中完成,缺省行为移到父类中完 成。 n 这样做不仅代码数量减少,而且也减 少了潜在的出错机会。 n 假如要增加一个新的子类,只需要保 证这个类实现正确的接口即可。 Pet p= ; P.newMethod(); 6/7/202188 n Object newValue = aClass.newInstance(); / Java 6/7/202189 n ClassLoader主要用于加载类文件,利用反射(newInstance()生成类 实例 n 假设有类

36、A和类B,A在方法amethod里需要实例化B n 其中一种方式就是使用ClassLoader /* Step 1. Get ClassLoader */ ClassLoader cl=this.getClass.getClassLoader() n /* Step 2. Load the class */ Class cls = cl.loadClass(com.rain.B); / 使用第一步得到的 ClassLoader来载入B /* Step 3. new instance */ B b = (B)cls.newInstance(); / 有B的类得到一个B的实例 6/7/202190

37、 n 反射支持一个组件动态的加载和查询 自身信息,因此反射为许多基于组件 的编程工具建立了基础。 6/7/202191 得到某个对象的属性 public Object getProperty(Object owner, String fieldName) throws Exception Class ownerClass = owner.getClass(); Field field = ownerClass.getField(fieldName); Object property = field.get(owner); return property; 6/7/202192 得到某个类的静态属性 public Object getStaticProperty(String className, String fieldName) throws Exception Class ownerClass = Class.forName(className); Field field = ownerClass.getField(fieldName); Object property = field.get(ownerClass); return property; 6/7/202193

温馨提示

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

评论

0/150

提交评论