05面向?qū)ο箢?、方法、消息、實例_第1頁
05面向?qū)ο箢?、方法、消息、實例_第2頁
05面向?qū)ο箢?、方法、消息、實例_第3頁
05面向?qū)ο箢?、方法、消息、實例_第4頁
05面向?qū)ο箢?、方法、消息、實例_第5頁
已閱讀5頁,還剩92頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、類和方法 2021-6-7 n 利用數(shù)據(jù)抽象進行編程。 n 數(shù)據(jù)類型兩個方面:外部用戶/實現(xiàn)者 6/7/20212 6/7/20213 n 避免重復(fù)的代碼 n 保護類受到不必要的修改 n 實例 n 實例變量/數(shù)據(jù)成員/數(shù)據(jù)字段 n 對象=狀態(tài)(實例變量)+行為(方法) 對象外部看,客戶只能看到對象的行為; 對象內(nèi)部看,方法通過修改對象的狀 態(tài),以及和其他對象的相互作用,提 供了適當(dāng)?shù)男袨椤?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 數(shù)據(jù)字段private n Accessor(Getter)/Setter/Is 6/7/202110 n 無可視性修飾符 n 數(shù)據(jù)均private 6/7/202111 n 先列出主要特征,次要的列在后面。 n 私有數(shù)據(jù)字段列在后面。 n 構(gòu)造函數(shù)列在前面。 6/7/202112 n Java,C#:方法主

4、體直接放在類定義中。 n C+:分離 n 可讀性? 6/7/202113 n 接口 1.不提供實現(xiàn) 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 類的數(shù)據(jù)字段 n (類屬性) 1.被一個類的所有實例共享的公共數(shù)據(jù) 字段。 2.如何對該字段初始化? 6/7/202118 1.每個實例都執(zhí)行對公共數(shù)據(jù)字段的初 始化? 2.沒有實例執(zhí)行初始化

6、任務(wù)? 3.對象本身不對共享字段初始化。內(nèi)存 管理器自動將共享數(shù)據(jù)初始化為某特 定值,每個實例去測試該特定值。第 一個進行測試的做初始化。 6/7/202119 n Java和C+使用修飾符static創(chuàng)建共享 數(shù)據(jù)字段。 4.Java:靜態(tài)數(shù)據(jù)字段的初始化是在加載 類時,執(zhí)行靜態(tài)塊來完成。 6/7/202120 /某類已經(jīng)創(chuàng)建了多少實例? 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.由基本數(shù)據(jù)類型表示的靜態(tài)數(shù)據(jù)字段 可以在類的主體中進行初始化。 2.在類外對靜態(tài)數(shù)據(jù)字段進行初始化。 6/7/202122 class CountingClass public: CountingClass () count+; . private: static int count; ; / global initialization is separate from class int CountingClass:count = 0; 類型 類名:靜態(tài)成員=值 6/7/202123 n 實現(xiàn)同類多個對象間的數(shù)據(jù)共享

8、。 n 計數(shù)器 6/7/202124 n 成員函數(shù)。不能訪問非靜態(tài)成員。 n 無this n 構(gòu)造和析構(gòu)函數(shù)不能為靜態(tài)成員。 6/7/202125 山東大學(xué)計算機學(xué)院26 Java同時也包含無對象(objectless)變量及無對象方法, 稱為類變量和類方法 實際上,通過使用Java的這些無對象特性,可以編寫一 個幾乎完全非面向?qū)ο蟮爻绦颉?類變量的典型使用方式是定義常量。 這樣的常量不僅被該類的所有對象共享,而且通常被聲 明為公共變量,以供給該程序中所有的對象和類使用 除了用來定義常量以外,類變量也可以用來使得某類所 有的實例(對象)共享一份數(shù)據(jù) 山東大學(xué)計算機學(xué)院27 類方法可以被視為可獨

9、立于某類的所有對象而進行調(diào)用 的方法,而非傳遞給該類的對象的消息。 類方法能在不引用Math對象的情況下,被Java代碼中 的任何主體存取和執(zhí)行。 山東大學(xué)計算機學(xué)院28 當(dāng)定義類并且確定該類應(yīng)當(dāng)包含何種方法,是類方法還是 實例方法時,通常并不是一目了然的。 比如,假設(shè)要定義一個Set類(不同于java.util.Set接口), 其對象行為類似于數(shù)學(xué)概念上的(有限、無序)整數(shù)集合。 對于這樣一個集合很自然的操作便是與另一個Set對象求 交集。對于該Set類,這樣的操作有如下(至少)兩個版 本的聲明方式: Public Set intersect (Set otherSet) Public st

10、atic Set intersect (Set firstSet, Set secondSet) 哪個版本更好呢? 山東大學(xué)計算機學(xué)院29 將大段的代碼分解為方法,并且將代碼段替代為方法調(diào)用, 可以允許編程人員在更高的層次上來考慮計算過程。 這樣,方法就提高了代碼的可讀性。這種將代碼分解為方 法的過程成為功能分解(functional decomposition) 將代碼分解為設(shè)計良好的方法不僅能提高代碼的可讀性, 還能提高代碼的可重用性 一個設(shè)計良好的方法可以成為編程人員的另一種工具,讓 編程人員可以在需要完成特定目標的時候隨時使用 山東大學(xué)計算機學(xué)院30 什么時候需要把一個方法分解為另外的

11、方法呢?一個最簡 單的經(jīng)驗法則就是,如果方法體不能同時在電腦屏幕中完 全顯示,它可能就太長了,需要將一些工作轉(zhuǎn)交給其他方 法。 當(dāng)有代碼冗余的時候也需要考慮進行分解。也就是說,如 果某程序有兩個部分的指令執(zhí)行序列完全一致,那么更好 的做法就是,將這個一樣的代碼移至一個單獨的方法中, 并將原來的代碼替換為一個方法調(diào)用。 山東大學(xué)計算機學(xué)院31 對于刪除Java中構(gòu)造函數(shù)里的代碼冗余還有一個特殊的稱 為構(gòu)造函:函數(shù)鏈(constructor chaining)的機制。 這是關(guān)于一個構(gòu)造函數(shù)通過“this”調(diào)用另一個構(gòu)造函數(shù) 的機制。比如,考慮如下具有兩個構(gòu)造函數(shù)的類。它假設(shè) 一個家庭總是有一位父親

12、、一位母親、零個或者多個孩子。 山東大學(xué)計算機學(xué)院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 . . ) 第二個構(gòu)造函數(shù)調(diào)用了第一個構(gòu)造函數(shù),因此它僅僅是一個允許用戶 不需要創(chuàng)建一個空的數(shù)組,來表明某家庭(還)沒有孩子的便捷構(gòu)造 函數(shù)。 山東大學(xué)計算機學(xué)

13、院33 方法的一個重要屬性就是它們應(yīng)該盡可能地獨立。 比如,如果某方法使用了實例變量或者調(diào)用了私有方法, 那么該方法就僅僅在該類的上下文中有用。 與之相反,如果該方法,通過參數(shù)得到所有數(shù)據(jù),并且根 據(jù)這些參數(shù)來實現(xiàn)方法調(diào)用的話,那么該方法就可以隨意 移動到任何類中,而這給了代碼組織更大的靈活性。 山東大學(xué)計算機學(xué)院34 方法的另一個重要屬性是,它們只實現(xiàn)一個功能。當(dāng)您建 立或者試圖建立一個方法時,試想一下您是否可以在不使 用“和”這個詞的情況下,用一個句子完全描述該方法做 了些什么。如果不能完全描述的話,該方法很可能需要被 分為兩個或者多個方法。 指導(dǎo)原則 一個方法應(yīng)該只實現(xiàn)一個任務(wù)并且要很好

14、地完成該任務(wù)。 該指導(dǎo)原則稱為組合方法 遵循該指導(dǎo)原則的方法被稱為具有很強的“功能內(nèi)聚”(functional cohesion) n 下面我們開始談?wù)劊?n 如何實例化?如何初始化?如何通過消息傳 遞來聯(lián)系? 6/7/202135 n 對象間相互請求或相互協(xié)作的途徑。 6/7/202136 n 消息-接收器。 n 響應(yīng)行為隨接收器不同而不同。 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 靜態(tài):類型和變量聯(lián)系在一起 (Java,C+,C#,Pascal) n 動態(tài):變量看作名稱標識,類型和數(shù) 值聯(lián)系在一起。(SmatllTalk,Python) n 編譯時刻檢查? 6/7/202139 n 面向?qū)ο箪o態(tài) n C

16、+,Delphi pascal,Eiffel,Java n 面向?qū)ο髣討B(tài) n Objective-c,Smalltalk,Dylan,Python 6/7/202140 n 非面向?qū)ο箪o態(tài) n Ada,Algol,C,Fortran,Haskell,ML,Mo dula n 非面向?qū)ο髣討B(tài) n APL,Forth,Lisp,Prolog,Snobol 6/7/202141 n 動態(tài)類型語言與靜態(tài)類型語言之間的 差異在于變量或數(shù)值是否具備類型這 種特性。 6/7/202142 n 焦點:高效性與靈活性 6/7/202143 n 編譯時作出內(nèi)存分配決定。不必運行 時刻重新分配。 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隱含指向調(diào)用成員函數(shù)的對象 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.數(shù)組的分配和創(chuàng)建 2.數(shù)組所包含對象的分配和創(chuàng)建 6/7/202149 n Java:new僅創(chuàng)建數(shù)組。數(shù)組包含的對 象必須獨立創(chuàng)建。 PlayingCard cardArray

19、= new PlayingCard13; for (int i = 0; i 13; i+) cardArrayi = new PlayingCard(Spade,i+1); 6/7/202150 n 數(shù)組子類化的問題 nString stringData=new String3“Larry”,”Curly”,”Moe”; nObject objectData=stringData nobjectData0=new Integer(3) 6/7/202151 n Java無指針? n 對象引用實際是存在于內(nèi)部表示中的 指針。 6/7/202152 n 使用new創(chuàng)建-堆內(nèi)存 n 堆內(nèi)存沒有綁定

20、在過程的入口和出口 處 n 內(nèi)存有限 1.在程序中顯式制定不再使用的對象, 將其使用內(nèi)存回收。 C+:delete Object Pascal:free 6/7/202153 2.垃圾回收機制(Java,C#,Smalltalk) n 時刻監(jiān)控對象的操作,對象不再使用 時,自動回收其所占內(nèi)存。 n 通常在內(nèi)存將要耗盡時工作。 6/7/202154 1.付出額外代價 2.避免釋放多次;避免使用已被釋放內(nèi) 存;避免耗盡內(nèi)存。 6/7/202155 1.確保動態(tài)分配的內(nèi)存對象都有一個指 定的屬主。 2.引用計數(shù):引用共享對象的指針的計 數(shù)值。 a=new C;b=new C;a=b; 6/7/202

21、156 n按照編譯原理的觀點,程序運行時 的內(nèi)存分配有三種策略,分別是靜態(tài) 的,棧式的,和堆式的。 6/7/202157 n 靜態(tài)存儲分配是指在編譯時就能確定每個數(shù)據(jù)目標 在運行時刻的存儲空間需求,因而在編譯時就可以給 他們分配固定的內(nèi)存空間。 n 這種分配策略要求程序代碼中不允許有可變數(shù)據(jù)結(jié) 構(gòu)(比如可變數(shù)組)的存在,也不允許有嵌套或者遞歸 的結(jié)構(gòu)出現(xiàn),因為它們都會導(dǎo)致編譯程序無法計算準 確的存儲空間需求。 6/7/202158 n 棧式存儲分配也可稱為動態(tài)存儲分配,是由一個類似 于堆棧的運行棧來實現(xiàn)的。 n 和靜態(tài)存儲分配相反,在棧式存儲方案中,程序?qū)?shù)據(jù) 區(qū)的需求在編譯時是完全未知的,只

22、有到運行的時候 才能夠知道,但是規(guī)定在運行中進入一個程序模塊時, 必須知道該程序模塊所需的數(shù)據(jù)區(qū)大小才能夠為其 分配內(nèi)存。 n 棧式存儲分配按照先進后出的原則進行分配。 6/7/202159 n 靜態(tài)存儲分配要求在編譯時能知道所有變量的存儲 要求,棧式存儲分配要求在過程的入口處必須知道所 有的存儲要求,而堆式存儲分配則專門負責(zé)在編譯時 或運行時模塊入口處都無法確定存儲要求的數(shù)據(jù)結(jié) 構(gòu)的內(nèi)存分配,比如可變長度串和對象實例。 n 堆由大片的可利用塊或空閑塊組成,堆中的內(nèi)存可以 按照任意順序分配和釋放。 6/7/202160 n 初始化新創(chuàng)建對象。 n 優(yōu)點:確保初始化之前不會被使用,防多次 調(diào)用

23、n Java/C+:名稱,返回值 6/7/202161 n Java和C#中數(shù)據(jù)字段可以初始化為特 定的數(shù)值。 n 構(gòu)造函數(shù)重載 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.缺省構(gòu)造函數(shù) 2.拷貝構(gòu)造函數(shù) 3.賦值操作符 4.析構(gòu)函數(shù) 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 當(dāng)一個類沒有自定義的拷貝構(gòu)造

27、 函數(shù)的時候系統(tǒng)會自動提供一 個默認的拷貝構(gòu)造函數(shù),來完 成復(fù)制工作 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僅斷言相關(guān)變量不會賦予新值, 并不能阻止在對象內(nèi)部對變量值進行 改變。如對消息的響應(yīng)。 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èi)存中開始釋放對象時,自動調(diào)用。 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.這個類所具有的行為:創(chuàng)建實例,返 回類名稱,返回類實例大小,返回類 實例可識別消息列表。 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、內(nèi)省(introspection) 是指程序在運行過程中“了解”自身 的能力。 6/7/202181 n用于反射和內(nèi)省的技術(shù)分為兩大類 n獲取理解當(dāng)前計算狀態(tài)的特征 n用于修改的特征:增加新的行為 n 反射工具都開始于一個對象,該對象 是關(guān)于一個類的動態(tài)(運行時)體現(xiàn)。 n 類對象是更一般的類(稱為Class類) 的實例。 n 類對象通常都包括類名稱、類實例所 占用內(nèi)存的大小以及創(chuàng)建新實例的能 力。 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 如何決定多態(tài)變量是否真正包含一個指定子類的 實例 n Child *c-dynamic_cast(aParentPtr); if (c!=0) /C+ n if (aVariable instanceof Child) if (aCalss.isInstance(aVariable) /Java 6/7/202186 n 如果下一步執(zhí)行的行為要依賴于多態(tài) 變量所包含的特定類型: Pet p=; if(p instanceof Cat) else if(p instanceof Dog

35、) else System.err.println(“Unknown”) 6/7/202187 n 建立一個新方法,子類特定行為移到 子類中完成,缺省行為移到父類中完 成。 n 這樣做不僅代碼數(shù)量減少,而且也減 少了潛在的出錯機會。 n 假如要增加一個新的子類,只需要保 證這個類實現(xiàn)正確的接口即可。 Pet p= ; P.newMethod(); 6/7/202188 n Object newValue = aClass.newInstance(); / Java 6/7/202189 n ClassLoader主要用于加載類文件,利用反射(newInstance()生成類 實例 n 假設(shè)有類

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 反射支持一個組件動態(tài)的加載和查詢 自身信息,因此反射為許多基于組件 的編程工具建立了基礎(chǔ)。 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 得到某個類的靜態(tài)屬性 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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論