命名的範圍很廣,從 Source Code 的檔案名稱到 Class 的名稱,Variable 的命稱,Method 的名稱等等都有其命名的習慣。 打個比方,在寫 Java 時,Java 的 Class 如下定義
class Car {
}
產生一個 Car class 其第一個字大寫是 Java 的命名習慣,而相對應這個 Source code 的檔案,也常命名為 Car.java,習慣就是 Java 的檔案名稱和其內容的第一個 Class 命稱一樣,大寫字開頭,這個是 Java 語言中的習慣。習慣指的是,即使語法沒有強制說不行,但是大家都這樣做。而 Objective-C 沒有這樣的習慣。
上述的 class 在 Objective-C 是這樣命名
@interface Car
@end
@implementation Car
@end
Class 的定義在 Objective-C 是分開的分為
@interface Car
@end
和
@implementation Car
@end
兩個部分。再來看看另一個語言 C# 是如下定義
class Car{
}
看起來和 Java 有點像,也沒有檔案名稱要和 class 命稱一樣命名的習慣。我們再來看看 Class 的內部命名習慣。
把剛剛的 class 加上 ivar 和 method.
Java 部分
class Car {
String name;
String getName(){
return name;
}
void setName(String newName){
name = newName;
}
}
新增了 name 這個變數 和 getName 還有 setName 這兩個 method。 getName 稱為 getter 而 setName
則為 setter 。
Java 的命名習慣就是,第一個字小寫,不論 variable 或是 method 的名稱。名詞和名詞之間後面接的名詞第一個字大寫,這種命西習慣稱為 CamelCase 駝峰式大小寫
再來看看 Objective-C 的命名習慣。
@interface Car:NSObject{
NSString * name;
}
@end
@implementation Car
-(NSString *) name{
return name;
}
-(void) setName:(NSString *) newName{
name = newName;
}
@end
Objective-C 的命名習慣和 Java 差不多,但是 getter 的地方不一樣,在 Objective-C getter 的名稱和要讀的變數名稱一樣。在這個例子兩者都叫 name。
我們再來看看類似的 class 在 C# 如何表現?
class Car{
string name;
public string GetName(){
return name;
}
public void SetName(string newName){
name = newName;
}
}
在 C# 中新增了 name 這個變數和 GetName 還有 SetName 這兩個 method。在這邊可以注意到 C# 的變數名稱是小寫開頭而 method 的名稱習慣用大寫字開頭。三種語言都有其個自的習慣,雖然不按照這個習慣,大部分情況下程式也是可以執行,但是在 Objective-C 如果不照者命名的習慣會造成一些奇怪的問題產生。
就讓我們來進入這篇文章的主題,開啟一個 ARC enable 的 Project 再加入一個 none ARC 的 class 就用上述的 Car 再加上兩個 method,讓我們一步一步來。
首先開啟一個 Single View Application 的專案如下
記得要勾選 Automatic Reference Counting
新增一個 Class 名為 Car 繼承 NSObject 如下是 Car.h
@interface Car : NSObject
-(id) newName;
-(id) newname;
@end
Car.m 如下
@implementation Car
-(id) newName{
return [NSString stringWithFormat:@"Honda"];
}
-(id) newname{
return [NSString stringWithFormat:@"Honda"];
}
@end
新增兩個 method 這兩個 method 的名稱很像,一個叫 newName 一個叫 newname 差別在於一個 name 有大寫的 N 另一個沒有。換句話說,newName 是有依照習慣命名,newname 是沒有的。
接下我們要把這個 Car.m 設定為不使用 ARC。
如下設定。
再新增一個 Button 在 畫面上,然後 Button 按下去 action 如下
- (IBAction)testCar:(id)sender {
Car * car = [Car new];
NSLog(@"Car name %@", [car newName]);
}
我們先使用這個 newName method。一執行,發現馬上就 crash。
但是如果換成 newname 這個 method 就是正常執行。
為什麼呢?
因為對於 non-ARC 的 method,ARC 會看其 method 的開頭是不是 alloc, new 或 copy (所謂開頭指的是符合 CamelCase 的第一個詞)或是
第一個是 mutable 第二個是 copy ,也就是寫成 mutableCopy 。此時 ARC 會自動認為這個 method 是會產生一個沒有加到 autorelease pool 的物件,然後就自行決定加上 release 在這個例子使用 newName 就 crash 是因為 newName 回傳的是
[NSString stringWithFormat:@"Honda"]這個有加到 autorelease pool 的物件。而 ARC 自動多 release 一次了。這個例子是要提示大家,在寫 method 的時候要注意 CamelCase 第一個字,這個就是 ARC 的習慣。
沒有留言:
張貼留言