《objective-c基礎教程》學習筆記(四)—— OC面向對象編程初探

  在上篇博文中,咱們編寫了一個能夠輸出不一樣幾何類型的小程序。經過C語言的struct結構體,給你們感覺了下,對象的大概樣子。編程

  若是用Obejctive-C的面向對象的特徵來實現。那麼,drawShape函數應該修改爲這樣:小程序

1 void drawShape(id shapes[], int count)
2 {
3     for(int i=0;i<count; i++)
4     {
5         id shape = shapes[i];
6         [shape draw];
7     }
8 }

  這裏,函數上傳入的id類型,是指泛型(即:能夠用來引用任意類型的對象)。這裏的指是一個包含struct結構體的對象。循環體中的id是一個指針類型,指針依次指向數組中的各個幾何對象。數組

  [shape draw]:這個寫法比較獨特,這裏的方括號不是像C語言中同樣,表示數組。在Objective-C中,方括號表示通知某個對象去作什麼操做(相似消息), 括號前第一個參數表示的是:對象,其他部分表示的是須要對象執行的操做ide

  那麼,[shape draw] 就能夠很好的理解爲:向對象shape發送draw的消息。函數

  經過上面改編例子的引入,接下來,就給你們大概的介紹下Objective-C的面向對象的相關內容。在正式轉入Objective-C編程以前,先給你們普及下面向對象的幾個基本概念。(詳細介紹,能夠請教度娘或者相關參考書)優化

    類(Class):是一種表示對象類型的結構體。
    對象(Object):是一種包含值,指向其餘類的隱藏指針的結構體。
    實例(Instance):是「對象」的另一種稱呼。
    消息(Message):是對象能夠執行的操做,用於通知對象去作什麼。
    方法(Method):是爲響應消息而運行的代碼。
    方法調度(Method Dispatcher):是Objective-C使用的一種機制。
    接口(Interface):是類爲對象提供的特性描述。
    實現(Implementation):是使接口能正常工做的代碼。
 
  好了,接下來我給你們介紹下,在Objective-C中,如何定義類和方法,以及如何使用。
 
1).  類的定義
1 @interface Circle: NSObject
2 @end

  定義了一個Circle類的接口,「:」表示的是繼承NSObject父類。以@interface開始,@end結束。
注:在Objective-C中,只要看到@符號,就能夠將其看中是C的擴展。

2). 方法的定義spa

  分爲兩種,對象方法和靜態方法: 對象方法 定義的時候,最前面用 減號 靜態方法(類方法)定義的時候,最前面用 加號
  通俗的講, 類方法,這類方法是能夠直接用類名來調用的,它的做用主要是建立一個實例。有人把它稱爲建立實例的工廠方法。 實例方法,要實例化,必須使用類的實例才能夠調用的。
1 @interface Circle: NSObject
2     -(void) setFillColor : (ShapeColor)fillColor;
3     -(void) setBounds : (ShapeRect) bounds;
4     -(void) draw;
5 @end
  調用的時候,要先實例化。Circle v_circle; -->  v_circle.setFillColor; 那麼,什麼是靜態方法呢?這裏給個基本例子:
1 @interface NSString : NSObject
2     +(id)string;
3     +(id)stringWithString:(NSString*)aString;
4     +(id)stringWithWithCString:(const char*)cString
5                         encoding:(NSStringEncoding)enc;
6 @end

  這個能夠直接用類名來調用。--> NSString.string;.net

PS:上面只是對方法進行了聲明,具體的方法還沒實現。在定義方法的時候,前一個括號中的表示返回值的類型,後一個表示調用這個方法要傳入的參數的類型。

3). 方法的實現3d

  通常建立Objective-C項目的時候,會自動建立兩個文件。.h結尾的頭文件和.m結尾的實現文件(這個.m相似C語言中的.c,C++中的.cpp)。指針

實現方法就寫在.m結尾的實現文件中,方法以下:

 1 #import "Shapes.h"
 2 @implementation Circle
 3     -(void) setFillColor :(ShapeColor)fillColor
 4     {
 5             ...  //具體實現的代碼1
 6     }
 7     -(void) setBounds :(ShapeRect)bounds
 8     {
 9             ... //具體實現的代碼2
10     }
11     -(void) draw
12     {
13             ... // 具體實現的代碼3
14     }
15 @end

  在Objective-C中,有一種叫中綴符的語法技術。方法的名稱和參數能夠合在一塊兒。

例如:

[circle setFillColor: kRedColor];

那麼,帶兩個參數的方法如何調用呢?方法以下:

[textThing setStringValue: @"hello there" color: kBlueColor];

  好了,那麼接下來。咱們就將上一篇博文中的代碼修改爲用Objective-C的語法的吧。

  1 //
  2 //  main.m
  3 //  ch4_OOP_Shapes_OC
  4 //
  5 //  Created by pcbeta on 14-11-18.
  6 //  Copyright (c) 2014年 julian. All rights reserved.
  7 //  面向對象的基本實例,繪製幾個幾何圖形,修改爲Objective-C版本
  8 //-------------------------------------修改版,修改Objective_C-------------------------------
  9 
 10 /* 1. enum 枚舉類型 */
 11 //定義繪製圖形的類型: 圓形,矩形,橢圓形
 12 typedef enum{
 13     kCircle,
 14     kRectangle,
 15     kEgg
 16 } ShapeType;
 17 
 18 //定義繪製圖形的顏色: 紅色,綠色和藍色
 19 typedef enum{
 20     kRedColor,
 21     kGreenColor,
 22     kBlueColor
 23 } ShapeColor;
 24 
 25 /* 2. struct 結構體 */
 26 //定義圖形的基本屬性
 27 typedef struct{
 28     int x, y, width, height;
 29 } ShapeRect;
 30 
 31 //定義總體描述的形狀
 32 typedef struct{
 33     ShapeType type;
 34     ShapeColor fillColor;
 35     ShapeRect bounds;
 36 } Shape;
 37 
 38 /* 3.定義獲取顏色名稱的函數 */
 39 NSString *colorName (ShapeColor fillColor)
 40 {
 41     switch(fillColor)
 42     {
 43         case kRedColor:
 44             return @"red";
 45             break;
 46         case kGreenColor:
 47             return @"green";
 48             break;
 49         case kBlueColor:
 50             return @"blue";
 51             break;
 52     }
 53 }
 54 
 55 //定義一個圓和實現方法
 56 @interface Circle : NSObject
 57 {
 58 @private ShapeColor fillColor;
 59     ShapeRect bounds;
 60 }
 61 -(void) setFillColor : (ShapeColor)fillColor;
 62 -(void) setBounds:(ShapeRect) bounds;
 63 -(void) draw;
 64 @end
 65 
 66 @implementation Circle
 67 -(void) setFillColor:(ShapeColor) c
 68 {
 69     fillColor = c; //fillColor爲實例變量,爲了防止同名,傳入的參數要取別名
 70 }
 71 -(void) setBounds:(ShapeRect)b
 72 {
 73     bounds = b;
 74 }
 75 -(void) draw
 76 {
 77     NSLog(@"drawing a circle at (%d %d %d %d) in %@",
 78           bounds.x,
 79           bounds.y,
 80           bounds.height,
 81           bounds.width,
 82           colorName(fillColor));
 83 }
 84 @end
 85 
 86 //定義一個矩形和實現方法
 87 @interface Rectangle : NSObject
 88 {
 89 @private ShapeColor fillColor;
 90     ShapeRect bounds;
 91 }
 92 -(void) setFillColor : (ShapeColor)fillColor;
 93 -(void) setBounds:(ShapeRect) bounds;
 94 -(void) draw;
 95 @end
 96 
 97 @implementation Rectangle
 98 -(void) setFillColor:(ShapeColor) c
 99 {
100     fillColor = c; //fillColor爲實例變量,爲了防止同名,傳入的參數要取別名
101 }
102 -(void) setBounds:(ShapeRect)b
103 {
104     bounds = b;
105 }
106 -(void) draw
107 {
108     NSLog(@"drawing a rectangle at (%d %d %d %d) in %@",
109           bounds.x,
110           bounds.y,
111           bounds.height,
112           bounds.width,
113           colorName(fillColor));
114 }
115 @end
116 
117 //定義一個橢圓和實現方法
118 @interface Egg : NSObject
119 {
120 @private ShapeColor fillColor;
121     ShapeRect bounds;
122 }
123 -(void) setFillColor : (ShapeColor)fillColor;
124 -(void) setBounds:(ShapeRect) bounds;
125 -(void) draw;
126 @end
127 
128 @implementation Egg
129 -(void) setFillColor:(ShapeColor) c
130 {
131     fillColor = c; //fillColor爲實例變量,爲了防止同名,傳入的參數要取別名
132 }
133 -(void) setBounds:(ShapeRect)b
134 {
135     bounds = b;
136 }
137 -(void) draw
138 {
139     NSLog(@"drawing a egg at (%d %d %d %d) in %@",
140           bounds.x,
141           bounds.y,
142           bounds.height,
143           bounds.width,
144           colorName(fillColor));
145 }
146 @end
147 
148 void drawShape(id shapes[], int count)
149 {
150     for(int i=0;i<count;i++)
151     {
152         id shape = shapes[i];
153         [shape draw];
154     }
155 }
156 
157 int main(int argc, const char * argv[])
158 {
159     // 定義三個幾何圖形的數組
160     id shapes[3];
161     // 定義第一個幾何圖形爲 紅色的圓形,
162     ShapeRect rect0 ={0,0,10,30};
163     shapes[0] =[Circle new];
164     [shapes[0] setBounds: rect0];
165     [shapes[0] setFillColor: kRedColor];
166     
167     // 定義第二個幾何圖形爲 綠色的矩形,
168     ShapeRect rect1 ={30,40,50,60};
169     shapes[1] =[Rectangle new];
170     [shapes[1] setBounds: rect1];
171     [shapes[1] setFillColor: kGreenColor];
172     
173     // 定義第三個幾何圖形爲 藍色的橢圓形,
174     ShapeRect rect2 ={15,18,37,29};
175     shapes[2] = [Egg new];
176     [shapes[2] setBounds: rect2];
177     [shapes[2] setFillColor: kBlueColor];
178     
179     drawShape(shapes, 3);
180     
181     return 0;
182 }
View Code

  在運行上面代碼的時候,我發現一個書本上沒有說起的問題。那就是如圖:

  有兩個錯誤提示,以前覺得是代碼寫的錯誤。可是反覆查閱,仍是沒有發現問題。

後來,經過查詢錯誤信息(參考:http://blog.csdn.net/wbw1985/article/details/7644815)。

找出了錯誤緣由:因爲 XCode5.1 中缺省ARC(內存管理的一種模式,後面講內存管理的時候會詳細介紹)就是 ON 的狀態,因此編譯舊代碼的時候每每有"Automatic Reference Counting Issue"的錯誤信息。

解決的方法是:將項目編譯設置中的「Objectice-C Auto Reference Counteting」設爲NO。以下所示:

  設置完以後點擊保存,錯誤提示就消失了。這個時候點擊運行按鈕,就能夠看到運行結果如圖:

  可是,經過今天修改過的Objective-C的例子,咱們能夠看出代碼中了有不少地方都是重複的。

好比定義和實現Circle,Rectangle,Egg的代碼,基本都是重複的,這就很很大的優化空間了。

  下篇博文,咱們將繼續延續這個例子展開。介紹下Objective-C中繼承方法的使用。

相關文章
相關標籤/搜索