objective-c 文法快速過(3),objective-c文法

來源:互聯網
上載者:User

objective-c 文法快速過(3),objective-c文法

oc 裡的匿名對象 

 oc 這裡,很少用到,因為並不適用於oc的記憶體管理,只是面試筆試也許出現,要求能看懂,不要在項目裡這樣寫,因為寫匿名對象,會造成記憶體泄露

#import <Foundation/Foundation.h>@interface Car : NSObject{    @public    int speed;}- (void)run;@end@implementation Car- (void)run{    NSLog(@"%d", speed);}@endint main(){    //所謂匿名對象,就是沒有名字的對象,看不到,但是對象確實存在    [Car new]->speed = 300;//沒有指標變數指向對象,而是直接調用類的成員變數,因為每次使用[Car new]都會從新建立一個新對象,故不是300,而是預設初始化的值0    [[Car new] run];//0       // Car *c = [Car new];   // c->speed = 100;   // [c run];//100    return 0;}

能看懂什麼意思就行

類的成員變數的命名規範
  • 成員變數都以底線 _ 開頭
  • 可以跟get方法的名稱區分開
  • 可以跟其他局部變數區分開,一看到底線開頭的變數,肯定是類的成員變數
OC弱文法

1、OC是動態檢測錯誤,OC裡調用一個沒有聲明也沒有實現的對象方法,則不會編譯報錯而是警告,連結也能通過,只有運行才檢測出錯

2、Oc裡調用只有聲明,但是沒有實現的對象方法,這編譯也是警告,連結通過,運行才出錯

3、Oc調用只有實現(沒聲明)的方法,則沒有問題!因為運行時才檢測程式的問題,聲明其實只是擺設,刪掉是沒事的。只不過開發中,必須規範!該寫都要寫上。即使不報錯。

類方法

直接可以用類名來執行的方法(類本身會在記憶體中佔據儲存空間,裡面有類\對象方法列表)

1.  類方法和對象方法對比

1)   對象方法

  • 減號-開頭
  • 只能讓對象調用,沒有對象,這個方法根本不可能被執行
  • 對象方法能訪問執行個體變數(成員變數)

2)   類方法

  • 加號+開頭
  • 只能用類名調用,對象不能調用
  • 類方法中不能訪問執行個體變數(成員變數)
  • 使用場合:當不需要訪問成員變數的時候,盡量用類方法

3)       類方法和對象方法可以同名

4)       提高程式效能

類方法的好處和使用場合:不依賴於對象,執行效率高, 能用類方法,盡量用類方法

// 類方法都是以+開頭+ (void)printClassName;- (void)test;+ (void)test; //可以允許類方法和對象方法同名

self 關鍵字用來指明對象是當前方法的接收者。 

  • 當成員變數和局部變數同名時,採取就近原則,訪問的是局部變數
  • 用self訪問成員變數,區分同名的局部變數

細節:

1)    出現的地方:可以出現在所有的OC方法中(對象方法\類方法),但是不能出現在函數裡

2)    作用:

使用 "self->成員變數名" 訪問當前方法調用的成員變數

使用 "[self 方法名];" 來調用方法(對象方法\類方法)

#import <Foundation/Foundation.h>@interface Person : NSObject{    int _age;}- (void)setAge:(int)age;- (int)age;- (void)test;@end@implementation Person- (void)setAge:(int)age{    // _age = age;相當於    self->_age = age;}- (int)age{    return self->_age;}- (void)test{    // self:指向了方向調用者,代表著當前對象    int _age = 20;    NSLog(@"Person的年齡是%d歲", self->_age);}@endint main(){    Person *p = [Person new];        [p setAge:10];        [p test];        return 0;}/* self的用途: 1> 誰調用了當前方法,self就代表誰 * self出現在對象方法中,self就代表對象 * self出現在類方法中,self就代表類 2> 在對象方法利用"self->成員變數名"訪問當前對象內部的成員變[self 方法名]可以調用其他對象方法\類方法 */#import <Foundation/Foundation.h>@interface Dog : NSObject- (void)bark;- (void)run;@end@implementation Dog- (void)bark{    NSLog(@"汪汪汪");}- (void)run{    [self bark];//self代表指標d指向的對象,NSLog(@"汪汪汪");    NSLog(@"跑跑跑");}@endint main(){    Dog *d = [Dog new];        [d run];        return 0;}

低級錯誤:

用self去調用函數

類方法中用self調用對象方法,對象方法中用self調用類方法

self死迴圈

#import <Foundation/Foundation.h>@interface Person : NSObject- (void)test;+ (void)test;- (void)test1;+ (void)test2;- (void)haha1;+ (void)haha2;@end@implementation Person- (void)test{    NSLog(@"調用了-test方法");    // 如果有[self text];這句,就會引發死迴圈。因為[self test];self代表對象,一直調用對象方法test}+ (void)test{    NSLog(@"調用了+test方法");    // 引發死迴圈 [self test];self代表類,一直調用類方法test}//自動識別- (void)test1{    [self test]; // ok,-test}+ (void)test2{    [self test]; // ok,+test}- (void)haha1{    NSLog(@"haha1-----");}//函數void haha3(){  }+ (void)haha2{     haha3();//ok,一定注意函數和方法是不一樣的!    //[self haha3];//error,不能用self調用函數    //[self haha1];//error,類方法裡,不能用self調用對象方法,相反,在對象方法裡,也不能用self調用類方法}@endint main(){    [Person haha2];//直接調用類方法    //Person *p = [Person new];    //[p test1];    return 0;}

 

原則上(如果不使用 ARC,也就是自動引用計數),那麼

建立一個新對象,都要請求分配記憶體,在完成對該對象的操作時,必須釋放其所用的記憶體空間。類似 c++的記憶體管理。

 

與 C 語言相容的地方:

預先處理:

#define 語句和 c 一樣

#運算子: #define str(x) #x

表示在調用該宏時,預先處理程式根據宏參數建立C 風格的常量字串。

例如:str("hello")將產生"\"hello"\"

##運算子:表示用於把兩個標記連在一起

#import 語句;相當於#include 語句,但是 #import 可自動防止同一個檔案被匯入多次。

#條件編譯語句(#ifdef 、#endif 、 #else 、 #ifndef)和 C 一樣

#undef 語句 消除特定名稱的定義


其他基本的C 語言特性:

數組、函數、指標、結構、聯合的用法和C 一樣。

Compound Literal 是包含在括弧之內的類型名稱,之後是一個初始化列表。

例如

如果 intPtr 為 int * 類型:
intPtr = (int[100]){[0] = 1, [50] = 50, [99] = 99};

如果數組大小沒有說明,則有初始化列表確定。

其他如迴圈語句 (do while、while、for) 、條件陳述式(if 語句(if-else、複合判斷條件等) 、switch 語句)、 Boolean(YES NO)、條件運算子、goto 語句、空語句、逗號運算式、sizeof 運算子、命令列參數、位操作都 和 C 一樣 。

oc 的繼承

oc的繼承只支援單一繼承,和java類似,也就是兒子只能有一個爸爸,但是

可以通過 Objective-C 的分類和協議特性擷取多繼承的優點 

而c++支援單一和多重繼承。

好處:

不改變原來模型的基礎上,拓充方法

建立了類與類之間的聯絡

抽取了公用代碼

壞處:

耦合性強

基本上所有類的根類是NSObject類

animal類擁有NSObject類的new方法,子類dog和cat同時擁有前兩層類的所有方法和屬性。類似 c++和 java

#import <Foundation/Foundation.h>/* 1.繼承的好處: 1> 抽取重複代碼 2> 建立了類之間的關係 3> 子類可以擁有父類中的所有成員變數和方法 2.注意點 1> 基本上所有類的根類是NSObject *//********Animal的聲明*******/@interface Animal : NSObject{    int _age;    double _weight;}- (void)setAge:(int)age;- (int)age;- (void)setWeight:(double)weight;- (double)weight;@end/********Animal的實現*******/@implementation Animal- (void)setAge:(int)age{    _age = age;}- (int)age{    return _age;}- (void)setWeight:(double)weight{    _weight = weight;}- (double)weight{    return _weight;}@end/********Dog*******/// 繼承了Animal,相當於擁有了Animal裡面的所有成員變數和方法// Animal稱為Dog的父類,Dog稱為Animal的子類@interface Dog : Animal@end@implementation Dog@end/********Cat*******/@interface Cat : Animal@end@implementation Cat@endint main(){    Dog *d = [Dog new];        [d setAge:10];        NSLog(@"age=%d", [d age]);    return 0;}

oc 繼承裡的細節(類似其他物件導向語言)

父類必須聲明在子類的前面

子類和父類不能有相同的成員變數,但是方法可以重寫

方法的重寫問題:子類重新實現父類中的某個方法,也就是覆蓋了父法

調用某個方法時,優先去當前類中找,如果找不到,去父類中找

這是內部原理。

每個對象都有一個isa指標,指向對象屬於的類,且記住:每個類裡(oc的)都有一個superclass指標,指向自己的父類。

這樣通過對象就能找到對象屬於的類,也能找到類的父類。而這些指標就在NSSobject類裡。

記憶體結構:

繼承的使用場合

 1> 當兩個類擁有相同屬性和方法的時候,就可以將相同的東西抽取到一個父類中

 2> 當A類完全擁有B類中的部分屬性和方法時,可以考慮讓B類繼承A類

 // 繼承:xx 是 xxx

 // 組合(也叫彙總關係):xxx 擁有 xxx

super關鍵字

實現重寫之後,還可以調用父類的對象方法和類方法,super的作用;直接調用父類中的某個方法

 1、super處在對象方法中,那麼就會調用父類的對象方法

 2、super處在類方法中,那麼就會調用父類的類方法

使用場合:

子類重寫父類的方法時想保留父類的一些行為。

在oc裡,簡單的多,調用某方法,先是在所在類就近找,找不到去父類找。太簡單了。如果重寫了父類方法,那麼只能調用子類重寫的這個方法了,如果想保留父類原方法定義的功能,可以用super。

oc 的多態

多態的體現

Person *p = [Student new];

p->age = 100;

[p walk];

子類對象賦值給父類指標,父類指標訪問對應的子類的繼承來的屬性和方法

多態的局限性

不能訪問子類的特有的屬性或方法(可以考慮強制轉換)

多態的細節

動態綁定:在運行時根據對象的類型確定動態調用的方法

注意點:

 1.沒有繼承就沒有多態

 2.代碼的體現:父類類型的指標指向子類對象

 3.好處:如果函數\方法參數中使用的是父類類型,可以傳入父類、或者子類對象

 4.局限性:父類類型的變數 不能 直接調用子類特有的方法。必須強轉為子類類型變數後,才能直接調用子類特有的方法(類似c++的賦值相容)

#import <Foundation/Foundation.h>// 動物@interface Animal : NSObject- (void)eat;@end@implementation Animal- (void)eat{    NSLog(@"Animal-吃東西----");}@end// 狗@interface Dog : Animal- (void)run;//子類新增的對象方法run@end@implementation  Dog- (void)run{    NSLog(@"Dog---跑起來");}- (void)eat//重寫父類的-eat方法{    NSLog(@"Dog-吃東西----");}@end// 貓@interface Cat : Animal@end@implementation Cat- (void)eat//重寫父類的對象方法eat{    NSLog(@"Cat-吃東西----");}@end// 如果參數中使用的是父類類型指標,可以傳入父類or子類對象void feed(Animal *a){    [a eat];}int main(){    Animal *aa = [Dog new];//父類指標指向子類的對象    //[aa run];弱文法,只警告!但是在java或者c++裡,早就報錯了!父類指標不能訪問子類特有的方法,雖然弱文法,但不推薦,自己要認為是錯的    // 將父類對象aa轉為子類 Dog * 類型的變數就ok了,和c++類似    Dog *dd = (Dog *)aa;    [dd run];//ok,訪問的是子類的對象方法 run         //Dog *d = [Dog new];    //[d run];//ok        /* Animal *aa = [Animal new];父類對象的指標aa    feed(aa);可以傳入父類對象做參數,調用的父類的eat方法    Dog *dd = [Dog new];子類對象指標dd    feed(dd); 也可以傳入子類的對象做參數,調用的子類的eat方法    Cat *cc = [Cat new];    feed(cc);調用子類eat,傳入子類對象參數   */    // 多態:父類指標指向子類對象    Animal *a = [Dog new];    // 調用方法時會檢測對象的真實形象,動態    [a eat];調用的時子類的eat方法    */    return 0;}

多態的局限性:

父類類型的變數 不能 直接 調用子類特有的方法。

聯絡c++

c++是使用了虛函數,(包括純虛函數和抽象類別)對公有繼承的子類的方法,重寫虛函數,父類指標或者引用指向子類,那麼就能調用子類的重寫虛函數,指向父類,就是調用父類的虛函數,實現動態聯編。

oc裡,沒有那麼複雜,就是直接子類繼承父類,那麼重寫父類某個對象方法,這隻需要父類指標指向子類對象,那麼就調用子類的重寫方法,同樣也不能調用子類特有的方法。

由此斷定,oc的方法都是虛方法!不用和c++一樣用virtual聲明!且oc的重寫也是多態的一種,oc裡所有的方法訪問屬性都是公有的!而類成員變數預設是保護的。和c++有些區別,c++是預設都是私人的。

再看oc的弱文法!比如把子類對象指標指向父類

Cat *cat = [Animal new];

c++裡肯定錯誤,但oc裡沒問題,只警告,但這樣不好,不推薦。完全沒道理。

再看:

NSString *s = [Cat new];

動物怎麼了成了字串對象了?oc裡xcode不報錯!但是絕對是不對,不規範。還有,同一個層次的類,貓類指標指向狗類對象,調用eat方法,在oc的弱文法下,還是沒問題的,調狗的eat。

oc太弱了!但是在c++裡直接就報錯了。不可以這樣寫,即使編譯器不報錯。

多態的好處

用父類對象接收參數,方法或者函數,即可以接受子類對象,也能接受父類對象,節省代碼。否則還要分開寫多個方法或者函數。

充分體現物件導向的抽象和具體,通過子類重寫繼承來的父類的虛方法(oc預設都是),通過父類指標指向子類對象,實現動態多態性!不看指標的類型,而是看指標指向的哪個物件類型,就調用哪個子類對象的虛方法。注意子類特有的方法不可以,必須強轉。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.