Methods - 方法

來源于 Ry’s Objective-C Tutorial - RyPress

一個(gè)學(xué)習(xí)Objective-C基礎(chǔ)知識(shí)的網(wǎng)站.

個(gè)人覺得很棒,所以決定抽時(shí)間把章節(jié)翻譯一下.

本人的英語水平有限,有讓大家誤解或者迷惑的地方還請(qǐng)指正.

原文地址:http://rypress.com/tutorials/objective-c/methods.html

僅供學(xué)習(xí),如有轉(zhuǎn)摘,請(qǐng)注明出處.


方法代表著一個(gè)對(duì)象如何執(zhí)行操作.它們與代表著對(duì)象數(shù)據(jù)的屬性在邏輯上等同.你可以把方法當(dāng)做附加給對(duì)象的函數(shù),但他們有著不同的語法.

在這個(gè)模塊,我們將探討OC方法的命名規(guī)約,(這些規(guī)約)對(duì)有著C++,Java,Python以及其他類似語言的開發(fā)經(jīng)驗(yàn)人員來說,會(huì)比較frustrating(難受).我們也會(huì)簡(jiǎn)要的討論OC的訪問修飾符(用來設(shè)置訪問權(quán)限),并學(xué)習(xí)怎樣使用selectors(選擇器)關(guān)聯(lián)方法.

命名規(guī)約

OC的方法旨在(被設(shè)計(jì)成)移除API中任何含糊之處,所以導(dǎo)致了方法名很冗長(zhǎng)(啰嗦的嚇人),但是不可否認(rèn)的是,描述性很強(qiáng).遵守以下三條規(guī)則以實(shí)現(xiàn)OC方法的命名.
1.不要使用縮寫
2.明確規(guī)定方法自身的參數(shù)名
3.明確描述方法的返回值
在你閱讀下面的Car類接口時(shí)把這些規(guī)則記在心里.

// Car.h
#import <Foundation/Foundation.h>

@interface Car : NSObject

// Accessors
- (BOOL)isRunning;
- (void)setRunning:(BOOL)running;
- (NSString *)model;
- (void)setModel:(NSString *)model;

// Calculated values
- (double)maximumSpeed;
- (double)maximumSpeedUsingLocale:(NSLocale *)locale;

// Action methods
- (void)startEngine;
- (void)driveForDistance:(double)theDistance;
- (void)driveFromOrigin:(id)theOrigin toDestination:(id)theDestination;
- (void)turnByAngle:(double)theAngle;
- (void)turnToAngle:(double)theAngle;

// Error handling methods
- (BOOL)loadPassenger:(id)aPassenger error:(NSError **)error;

// Constructor methods
- (id)initWithModel:(NSString *)aModel;
- (id)initWithModel:(NSString *)aModel mileage:(double)theMileage;

// Comparison methods
- (BOOL)isEqualToCar:(Car *)anotherCar;
- (Car *)fasterCar:(Car *)anotherCar;
- (Car *)slowerCar:(Car *)anotherCar;

// Factory methods
+ (Car *)car;
+ (Car *)carWithModel:(NSString *)aModel;
+ (Car *)carWithModel:(NSString *)aModel mileage:(double)theMileage;

// Singleton methods
+ (Car *)sharedCar;

@end
縮寫

讓方法能夠被理解,被預(yù)料(可以被猜測(cè))的最簡(jiǎn)單方式就是避免縮寫.大多數(shù)OC編程人員都希望方法能被完全寫出,這是所有標(biāo)準(zhǔn)框架里的規(guī)約,從[Foundation](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/ _classic/_index.html)到UIKit都是這樣.這就是上述接口中選擇使用maximumSpeed取代更簡(jiǎn)寫的maxSpeed的原因.

參數(shù)

另一個(gè)清楚(反映)OC冗長(zhǎng)設(shè)計(jì)哲學(xué)的例子就是方法參數(shù)的命名規(guī)約.C++,Java以及其他類似風(fēng)格的語言中,將參數(shù)與方法分離成單獨(dú)的實(shí)體,而OC的方法名實(shí)則包括它所有的參數(shù)名.

舉個(gè)例子,在C++中為了讓Car(方向)轉(zhuǎn)90°,你也許會(huì)使用這樣turn(90)的方法.但是,OC覺著這太含糊了.搞不清楚turn()使用什么樣的參數(shù)-可能是一個(gè)新的方向角,也可能是在調(diào)整(增加)你當(dāng)前的方向角.OC方法通過一個(gè)介詞來描述讓它明確.這種方式實(shí)現(xiàn)的API保證了方法永遠(yuǎn)不會(huì)被誤用:它(方法)要么是turnByAngle:90.要么是turnToAngle:90.

當(dāng)一個(gè)方法可接受多個(gè)參數(shù)時(shí),那么每個(gè)參數(shù)名都被包含在方法名中.上面的例子中,initWithModel:mileage:方法把Model和mileage都帶上了.正如等會(huì)我們所見,這使得方法調(diào)用非常明確.

返回值

你肯定也注意到任何方法都返回一個(gè)明確狀態(tài)的值.有時(shí),會(huì)簡(jiǎn)單到只要說明返回的類型(class)就行,但其他時(shí)候,你需要增加一個(gè)形容詞做前綴.

比如,(上述的)工廠方法以car開頭,它明確說明該方法返回一個(gè)Car類型的實(shí)例.(再比如)那兩個(gè)比較方法,fasterCar:與slowerCar:返回接受者以及參數(shù)中的faster/slower,API也會(huì)被描述的很清楚.但對(duì)于單類方法,遵守這種模式?jīng)]有任何意義(比如,sharedCar),因?yàn)檫@種規(guī)約的實(shí)例方法名本身就是含糊的.

更多關(guān)于命名的規(guī)約,請(qǐng)方法官方的Cocoa Coding Guidlines文檔

方法調(diào)用

正如在實(shí)例化與使用章節(jié)討論過地,你通過在方括號(hào)中放置用空格分開的對(duì)象以及所需方法來執(zhí)行方法.參數(shù)與方法名用冒號(hào)分隔.

[porsche initWithModel:@"Porsche"];

當(dāng)有多個(gè)參數(shù)時(shí),則按照下面的方式,跟在初始參數(shù)之后.每個(gè)參數(shù)都有對(duì)應(yīng)的標(biāo)簽,并且需要用空格分隔,然后再跟上冒號(hào):

[porsche initWithModel:@"Porsche" mileage:42000.0];

當(dāng)你站在(方法)調(diào)用角度去看,就應(yīng)該更容易理解上述命名規(guī)約的目的了.它們(命名規(guī)約)是的方法調(diào)用讀起來像是人類語言,而非機(jī)器語言.比如,比較下面OC與其他語言的類似的方法調(diào)用:

// Python/Java/C++
porsche.drive("Home", "Airport");

// Objective-C
[porsche driveFromOrigin:@"Home" toDestination:@"Airport"];

這可能會(huì)有更多的種類(冗長(zhǎng)的方法名),所以Xcode 帶有如此好的自動(dòng)補(bǔ)全功能.當(dāng)你離開(遺忘)你的代碼,但是幾個(gè)月后再回來修復(fù) bug 時(shí),你就會(huì)對(duì)這種冗長(zhǎng)(的命名)感激萬分.這種清晰(冗長(zhǎng)的方法名)也使得使用第三方庫(kù)以及維護(hù)大型代碼庫(kù)變得更容易.

方法嵌套調(diào)用

嵌套調(diào)用方法是OC程序中常見的方式.把一個(gè)(方法)調(diào)用結(jié)果傳遞給另一個(gè)是很自然的.概念上來說,它們跟方法鏈(調(diào)用)完全一樣,只是方括號(hào)語法讓它們看起來有些不同罷了.

// JavaScript
Car.alloc().init()

// Objective-C
[[Car alloc] init];

[Car alloc]先被執(zhí)行,然后init方法被其返回值調(diào)用.

受保護(hù)以及私有方法

對(duì)于OC方法來說,沒有受保護(hù)或者私有的訪問修飾符-它們都是公有的.然而,OC提供了一種可替代的組織范例來讓你實(shí)現(xiàn)等同的效果.

"私有"方法可以通過在實(shí)現(xiàn)文件中定義,但是在接口文件中省略來創(chuàng)建.因?yàn)槠渌麑?duì)象(包括子類)永遠(yuǎn)不準(zhǔn)導(dǎo)入實(shí)現(xiàn)文件,所以,除了(定義這些方法的)類本身,這些方法有效地對(duì)其他對(duì)象隱藏了一切.

作為受保護(hù)方法的替代,OC提供了分類這種對(duì)隔離API更普遍的(大眾的)解決方案.我們會(huì)在Protected Methods中看到一個(gè)(關(guān)于分類的)完整的例子.

選擇器

選擇器是方法名在OC內(nèi)部的表示.它們?cè)试S你將一個(gè)方法當(dāng)做獨(dú)立的實(shí)體,從而你可以將(方法的)行為與需要執(zhí)行(該行為)的對(duì)象分離.這是目標(biāo)-行為設(shè)計(jì)模式的基礎(chǔ),這在Ry's Cocoa TutorialInterface Builder章節(jié)中有介紹.它也是OC動(dòng)態(tài)類型機(jī)制的組成部分.

可以通過兩種方式來得到方法名對(duì)應(yīng)的選擇器.@selector()指令,可以將源代碼中的方法名轉(zhuǎn)成選擇器,而NSSelectorFromString()函數(shù)則可以將一個(gè)字符轉(zhuǎn)成選擇器(這個(gè)沒有前者高效).這兩種方式都返回一個(gè)稱作SEL的特殊數(shù)據(jù)類型.SEL的使用與BOOL,int或者其他數(shù)據(jù)類型完全一樣.

// main.m
#import <Foundation/Foundation.h>
#import "Car.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Car *porsche = [[Car alloc] init];
        porsche.model = @"Porsche 911 Carrera";
        
        SEL stepOne = NSSelectorFromString(@"startEngine");
        SEL stepTwo = @selector(driveForDistance:);
        SEL stepThree = @selector(turnByAngle:quickly:);
        
        // This is the same as:
        // [porsche startEngine];
        [porsche performSelector:stepOne];

        // This is the same as:
        // [porsche driveForDistance:[NSNumber numberWithDouble:5.7]];
        [porsche performSelector:stepTwo
                      withObject:[NSNumber numberWithDouble:5.7]];
        
        if ([porsche respondsToSelector:stepThree]) {
            // This is the same as:
            // [porsche turnByAngle:[NSNumber numberWithDouble:90.0]
            //              quickly:[NSNumber numberWithBool:YES]];
            [porsche performSelector:stepThree
                          withObject:[NSNumber numberWithDouble:90.0]
                          withObject:[NSNumber numberWithBool:YES]];
        }
        NSLog(@"Step one: %@", NSStringFromSelector(stepOne));
    }
    return 0;
}

任何對(duì)象都可以通過performSelector:以及(其他)相關(guān)的方法來執(zhí)行選擇器.withObject:版本(方法)允許你給方法傳參數(shù),但是這些參數(shù)必須是對(duì)象.如果這對(duì)你的需求有太多限制,你可以查看NSInvocation的高級(jí)用法.當(dāng)你不確定目標(biāo)對(duì)象是否已定義了這個(gè)方法,那你應(yīng)該在嘗試執(zhí)行選擇器之前使用respondsToSelector:進(jìn)行檢查.

方法的術(shù)語名是串聯(lián)所有用冒號(hào)分隔參數(shù)標(biāo)簽得到的基本方法名(The technical name for a method is the primary method name concatenated with all of its parameter labels, separated by colons.這句翻譯的太難受了,自己理解吧).讓冒號(hào)成為方法名的一部分可能會(huì)讓剛學(xué)OC的人感到迷惑.它們的用法可以歸納如下:無參方法永遠(yuǎn)不包括冒號(hào),而有參的方法永遠(yuǎn)都是以冒號(hào)結(jié)尾.

下面是一個(gè)關(guān)于上述Car類的接口和實(shí)現(xiàn)的例子.請(qǐng)注意我們必須給performSelector:withObject:方法的參數(shù)傳遞NSNumber,而不是傳遞double(類型),因?yàn)樗辉试S你傳遞C語言的基本數(shù)據(jù)類型.

// Car.h
#import <Foundation/Foundation.h>

@interface Car : NSObject

@property (copy) NSString *model;

- (void)startEngine;
- (void)driveForDistance:(NSNumber *)theDistance;
- (void)turnByAngle:(NSNumber *)theAngle
            quickly:(NSNumber *)useParkingBrake;

@end
// Car.m
#import "Car.h"

@implementation Car

@synthesize model = _model;

- (void)startEngine {
    NSLog(@"Starting the %@'s engine", _model);
}

- (void)driveForDistance:(NSNumber *)theDistance {
    NSLog(@"The %@ just drove %0.1f miles",
          _model, [theDistance doubleValue]);
}

- (void)turnByAngle:(NSNumber *)theAngle
            quickly:(NSNumber *)useParkingBrake {
    if ([useParkingBrake boolValue]) {
        NSLog(@"The %@ is drifting around the corner!", _model);
    } else {
        NSLog(@"The %@ is making a gentle %0.1f degree turn",
              _model, [theAngle doubleValue]);
    }
}

@end

總結(jié)

這個(gè)模塊解釋了OC方法命名規(guī)約背后的原因,我們也知曉了OC方法中沒有訪問修飾符,知曉怎樣利用@selector去動(dòng)態(tài)地執(zhí)行方法.

適應(yīng)一種新的規(guī)約會(huì)是一個(gè)痛苦的(難受的)過程,并且這種OC與其他OOP語言的戲劇性語法差異不會(huì)讓你覺得輕松( and the dramatic syntactic differences between Objective-C and other OOP languages won’t make your life any easier.又是憂傷的一句).不要強(qiáng)迫自己把OC語言加到你頭腦中已存在的編程模型世界中,而是要去理解內(nèi)在的本質(zhì)(Instead of forcing Objective-C into your existing mental model of the programming universe, it helps to approach it in its own right. 更憂傷了).嘗試設(shè)計(jì)一些簡(jiǎn)單的程序之后,再給OC這種冗長(zhǎng)的(設(shè)計(jì))哲學(xué)下判斷下判斷.

那些(前些章節(jié))涵蓋了OC面向?qū)ο缶幊痰幕A(chǔ)(知識(shí)).這部教程的剩余內(nèi)容會(huì)探討更牛逼的方式來組織代碼.首先列出的是協(xié)議,它允許在多個(gè)類之間共享一個(gè)API.


寫于15年09月07號(hào)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,412評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,514評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,373評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,975評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,743評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,199評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,262評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,414評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,951評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,780評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,527評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,218評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,649評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,889評(píng)論 1 286
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,673評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,967評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容