這集開始講解Object-C的Method表示,和一些基本的Type。
我想跟C++一樣,開始要進入重點了。
我總是覺得,一種語言的重點就在於他是如何表示的。
整個表示式又各自代表什麼意思。
這才是重要的!
一旦搞懂,接下來就很好理解了。
讓我搞懂你吧!!!!
- Method Syntax: (method declaration)
- - (NSArray *) shipAtPoint: (CGPoint)bombLocation withDamage:(BOOL)damaged;
- 代表 instance method, +代表 class method。method declare 開頭不是 - 就是 + 。
(NSArray *) 代表的是 return type,意即回傳一個pointer to NSArray。void和在這邊不放任何東西在是完全不同的。若完全不放的話,代表回傳的是一個ID,也就是回傳任何物件。[還記得Object-C都是pointer to object 嗎?]。
shipAtPoint: withDamage: 代表這個函式的名稱[記得冒號也在裡面]。由於Object-C可以由左而右用英文念出來,故用 : 來代表參數所擺放的位置。
(CGPoint)第一個參數的型別。而(BOOL)是第二個參數的型別。若這裡沒有型別的話,亦代表這裡是個 ID。bombLocation是第一個參數的名字,damaged是第二個參數的名字。名字當然要能夠代表其意義。但另一個重點是:這裡不能是空白的。 - 遇到名字很長的時候,我們會將之斷行,並對齊冒號。
- (IBAction)型別與void是一樣的。但他代表指示子,告訴Interface Builder應該要注意這裡。
- case 1: (IBAction)digitPressed: (UIButton*) sender;
case 2: (IBAction)digitPressed: (ID) sender;
case 3: (IBAction)digitPressed: sender;
case 4: (IBAction)digitPressed;
case 1是表示 Interface Builder只會將 Button的物件與這個function作連結。而第二個代表任何物件皆可與這個function作連結。第三個與第二個相同,但不建議如此表示。因為會讓人誤會是否忘了放型別。應該確實表示你要表達的意義。而case 4則是會忽略任何參數。 - 送訊息可以指定self或super。self代表自己,而super代表把這個instance用父代來表示。
- Class Method的三種時機:
- allocation. e.g. +(id)alloc;
- global object. e.g. +(id)motherShip;
- utility function. e.g. +(int)turretsOnShipOfSize: (int)shipSize;這就不用任何實體就可以靠這 class method 得到該有的解答。
- 使用Class Method時,不能透過或存取物件的資訊。[這與c++一樣]
- variables:
- 沒有註明的話,預設為protected。使用@作為開頭。e.g.: @protected, @private...等等。
- 這老師希望我們將所有變數都使用private。少部份用protected。
- 使用 "dot notation" 來存取變數。這是種安全且方便使用的方法。
通常我們都會宣告getter與setter,這讓我們將控制範圍縮小。而dot notation有個命名規則。所有的variable都應該以小寫開頭。比方說:
@interface MyObject: NSObject
{
@private
int eye;
}
-(int) eye;
-(void)setEye: (int)anInt;
在這邊getter function就是跟變數名稱一樣,他讓我們可以直接讀取變數值。而setter的命名規則就是以set為開頭,後面加上變數名稱,變數名稱開頭大寫區隔兩字。必須遵照這樣的方法,dot notation才能使用。此時你將可以如此方便使用:
something.eye = otherEye; //setter
anotherEye = myObject.eye; //getter - 但這樣實在是太麻煩了,每個變數都要這樣設定實在太沒效率了。故@property就出現了。他很簡單的取代掉那兩個setter和getter。並如此宣告:
@interface MyObject: NSObject
{
@private
int eye;
}
@property int eye;
且這還可以指定 readonly。 e.g.: @property (readonly) int eye; 如此將不會有setter。 - 而事實上,variable的名稱不一定得跟@property宣告名稱一樣,甚至可以將variable拿掉直接變成如下:
@interface MyObject: NSObject
{
//@private
// int other_eye;
}
@property int eye;
@end
因為這樣的宣告並非是將getter與setter透過property來跟variable作連結。因為你在implement file (.m) 仍需實做出 -(int) eye 和 -(void) setEye: anInt 這兩個 getter 與setter functions。在這邊才指明哪個variable是要被 get 或 set 的。但是若是沒有variable呢?那麼通常是個readonly且裡面的值將會是計算出來的而非讀取出來的。 - 如此想想,在implement file還是要 key in那些getter和setter function。這樣的效率也沒提高到哪裡去。於是有個@synthesize出現了。e.g.:
@implementation MyObject
@synthesize eye;
@end
這樣表示variable eye將會自動做出 getter [-(int) eye ] 與 setter [-(void) setEye: anInt ]
那如果 variable name與 getter 或 setter取的名字不同呢?那就使用@synthesize eye = other_eye;
那如果沒有定義出variable呢?那就不能使用@synthesize。 - 當然,如果使用了@synthesize,依舊可以自行implement getter 或 setter function。
而@synthesize為我所創立的將會被我自行實做的取代掉。 - 很常見且很建議使用的是在實做中,透過 dot notation和 self 保留字 作結合。當你要存取你本身的變數的時候,使用self 和 dotnotaion是很方便閱讀且容易理解,當然在同一function出現太多次的話,你就給他個 local variable吧!另外,此時要小心的是:在getter與setter時,最好不要使用self with dot notation。否則會造成無窮迴圈。
- 如果需要一個private interface的話,可以在 implement file中的最上方宣告 interface,舉例:
@interface MyObject()
@property double myEyesOnly;
@end
一定要記得有括號。這邊可以有property,也可以有methods。然後在你的@implement實做出來。但切記不能有instance variables。所有的instance variable只能定義在header file中。而property為你創立的一樣要在@implement中實做出來。 - 總結一下,若是setting或getting,可以使用property,代表我們這行表示式是拿來作存取的。而method的invoke則用message傳遞的方式。如此可以明顯的在code中分辨。
- Binding
- 之前所提到的 NSString *S; 這些都是static binding。而id代表一個pointer指向一個物件。 而物件的型別不明。注意:永遠別使用id*。這是代表一個pointer指向一個pointer to object。
- 實際上NSStinrg*與id其實是一樣的。在Object-C的世界當中,所有的東西都是物件!故所有的處理都是 Dynamic Binding。而指明這個物件是NSString*的目的是跟Compilier說明這個物件在我們看來應該是怎樣的東西,好讓Compilier先幫我們去作一些型別的判斷,看看我們是否做了不是那型別能做的訊息發送或是其他誤用的情形。
- 如果 message發送給receiver沒有辦法處理這樣訊息,接收端本身或祖先沒辦法處理,則會發生crash。
- 當你知道你在做什麼的時候,你可以做cast的動作。
- 綜合以上,Compilier會去檢查Static Type裡面是否有你說的行為。若沒有,則會警告,若有,則沒事。
而若是宣告為id的話,則Compilier就不知道你指的是誰的行為了,他只知道有個物件要去做某種行為。若是這行為在不管哪個class有定義了,那Compilier就相安無事。但若Compilier找不到所指明的行為的話,則會警告。 - id在Collection的情況使用最好。i.e. Array。他讓這個Array可以裝任何的object。不像C/C++同一個Array只能有一種型別。 因此,我們在使用這樣的Array的時候,就要先詢問這個Array item是哪種 type,也就是introspection。
- 所有的物件都是繼承於NSObject。NSObject主要有三個重要的method分別是:isKindOfClass, isMemberOfClass, respondToSelector。
- isKindOfClass: 表示你是這類的Class嗎?繼承的也算在內。
e.g.: if( [obj isKindOfClass:[NSString class]]) {...} - isMemberOfClass: 表示你是這種Class嗎?只有這個Class才算,繼承的不算。
- respondToSelector: 表示我不管你是哪種Class,我只要你告訴我你有沒有支援這個method。
e.g.: if( [obj respondToSelector:@selector(method_name)]) {...}
@selector是一個特殊的定義,他會去看有沒有這樣的function。不管哪個class定義過。
method_name則是需要full method name,若是有多個參數則是:foo:bar:(要有冒號),但若是沒有參數則foo即可。
- 上述的@selector是Object-C中一種特別的型別,他的型別是SEL。
- nil
- nil是一個pointer,而他並沒有指向任何object。
- NSObject總是將他的變數都指向nil。所以他已經有初始值了。
- 送訊息給一個nil通常不會有提,他就不會執行而已。e.g.:
int i = [obj givemefive]; // i = 0 if obj is nil;
CGPoint position = [obj reportPosition] //if obj is nil, 因為是structure,所以position是nil,但他內含的屬性就是未定義。
- BOOL
- BOOL的值只有YES或是NO。全大寫。通常NO是0,YES是非0。但一般為了方便,就寫YES或NO就好。
- NSObject
- 在Object-C當中,最重要的基礎就是NSObject。他是Object-C中最原始的Class,每個物件都要源至於NSObject。他最重要的功能就是 Memory Management。他還有做introspection。
- 他內含另外一個很重要的 Method:-(NSString *) description。他可以override,用來描述這個class的敘述。
- NSString
- 可能是第二重要的物件了。他是Unicode,所以可以表達世界上任何語言。
- 當你使用@"foo",Compilier會為你創造一個NSString *指向一個物件,內含foo字串。
- 任何的NSString instance都是immutable,他們都是無法被改變的。當你建立他之後,這個instance內含值永遠就是那樣。上例就是一個NSString instance內含值永遠是foo。而當送訊息給一個NSString說要改變值的時候,NSString會建立另一個NSString instace回來,所以會同時有新值和舊值在這個Heap當中。
- 有另一個String Class是可被修改的:NSMutableString。他的內含值就是可以被修改。但是這就比較少用了。
- NSNumber
- 像int, float, double這種primitive type是沒辦法裝進 OO Array的,因為他們不是一個object 。而NSNumber是一個覆蓋的class,他可以將這種primitive type包裝成一種OO可以使用的 class。所以用NSNumber將primitive type包裝起來之後,你就可以把他裝到collection裡面了, e.g. NSArray or NSDictionary。
- NSValue
- 這是一種更一般化的包裝 Class。你可以把一些C struct的東西用這個NSValue包裝起來。
- Object-C已經將一般常用的C struct寫好他們的NSValue wrapper了, e.g.: CGPointer就能被NSValue給包裝起來。如果你要使用自己定義的struct的話,那得要自己寫wrapper。這就很少見了。
- NSData
- 這是個超級重要的Class。
- "Bag of bits": 沒structure過得data, e.g.: image, html pages。
- 很多iOS的API都使用NSData來傳送或儲存資料。
- NSDate
- date and time
沒有留言:
張貼留言