在上篇博文中,咱們編寫了一個能夠輸出不一樣幾何類型的小程序。經過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編程以前,先給你們普及下面向對象的幾個基本概念。(詳細介紹,能夠請教度娘或者相關參考書)優化
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
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 }
在運行上面代碼的時候,我發現一個書本上沒有說起的問題。那就是如圖:
有兩個錯誤提示,以前覺得是代碼寫的錯誤。可是反覆查閱,仍是沒有發現問題。
後來,經過查詢錯誤信息(參考: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中繼承方法的使用。