OC03三大特性學習


一、 面向對象特性之封裝

知識點

1.封裝說的是對成員變量的封裝和間接訪問
2.封裝涉及兩個對象方法:set方法和get方法
3.好處:①安全隱藏內部細節②set方法監聽成員變量的改變 一旦改變就做出相應處理行爲(**)
4.什麼情況下使用?只讀:只提供get方法 不要提供set或用@public,set方法一般都要寫。讀寫:兩者都要寫 
5.封裝逐漸成爲一種編程規範

命名規範

set方法的命名規範:
1)方法名必須以set開頭
2)set後面跟上成員變量的名稱並且成員變量的首字母必須大寫
3)返回值一定是void 
4)一定要接收參數,而且參數類型跟成員變量類型一致
5)形參的名稱不能和成員變量一樣
get方法的命名規範:
1)肯定有返回值,返回類型和成員變量類型一致
2)方法名和成員變量一樣
3)不需要接收參數       

代碼舉例

#import<Foundation/Foundation.h>
typedef enum
{
    SexMan,SexWoman
} Sex;
@interface Student:NSObject
{
    //@public 
    int age;
       //成員變量命名規範:一定要以下劃線 _開頭 和get方法的名稱區分開;   和局部變量也區分開來了
      Sex _sex;
}
//提供一個方法給外界設置age的屬性值 引出set方法 對傳來的參數進行過濾

- (void)study;

- (void)setAge:(int)newAge;
-(int)age;

- (void)setSex:(Sex)sex;
- (Sex)sex;
@end

@impementation Student
- (void)study
{
    NSLog(@“%d歲的學生在學習”,age);
}
//set方法的實現
- (void)setAge:(int)newAge
{
    if(newAge<=0)
    {
        newAge=1;
    }
    age=newAge;
}
- (int)age
{
    return age;
}
- (void)setSex:(Sex)sex
{
    _sex=sex;
}
- (Sex)sex;
{
    return _sex;
}
@end

int main()
{
    Student *stu=[Student new];
    //stu->age=20;//阻止不了公共類型的數據賦值,不能過濾不合理的數據 怎麼解決呢?(*1)
       [stu setAge:-10];//因爲此時age不是公共類型的 所以通過方法間接訪問
    [stu study];
       //int age=stu->age;//age是公共類型的時候
    int age=[stu age];
    [stu setSex:SexMan];
}
//*1去掉public 在set方法裏去判斷過濾 成員變量儘量不要用@public 【成員變量封裝】但是訪問是個問題 所以引入get方法

二、 弱語法理解

知識點

1.基於C 編譯時只發出警告,不報錯 【以上程序都是.m文件】
2.讓對象調用不存在的方法(沒有經過聲明)編譯只有警告,但是鏈接時卻沒錯 ,不過運行時會報錯:不能識別消息到實例 (程序自動終結)
unrecognized selector sent to instance 。。。。。
3.有聲明,沒有實現 編譯只有警告,但是鏈接時卻沒錯 ,不過運行時會報錯:找不到實現方法 
  這表明:OC在運行過程中才會檢測對象的類裏有沒有實現相應的方法(由上2可知)
4.無聲明,但有實現 編譯只有警告,但是鏈接時卻沒錯 ,運行也OK [由上2可知] (方法和類 通用 前提是在main函數之前)
 要是類 要這樣寫 @implementation Car:NSObject 
               @end
5.一旦程序運行時出錯,程序就會閃退。

代碼舉例

#import <Foundation/Foundation.h>

@interface Person : NSObject
- (void)test;
@end

@implementation Person
- (void)test
{
    NSLog(@"哈哈哈");
}
@end


/*
 -[Person test]: unrecognized selector sent to instance 0x7fd2ea4097c0
 給Person對象發送了一個不能識別的消息:test
 */

int main()
{
    Person *p = [Person new];
    // OC是在運行過程中才會檢測對象有沒有實現相應的方法
    [p test];
    return 0;
}

三、 類方法注意

知識點

1.類方法 通過類調用的方法 以加號 + 開頭
2.與對象方法的區別
    1)用對象調用類的方法 可以編譯通過,報錯:方法未找到 因爲對象的方法都是減號 - 開頭的
    2)用類調用對象的方法 可以編譯通過,報錯:方法未找到 因爲類的方法都是加號 + 開頭的

3.類方法和對象方法可以同名
4.類被加載到內存 
5.對象方法:只能由對象調用 減號 開頭 類方法:只能由類調用 加號 開頭

6.類方法不用依賴於對象 所以就不存在成員變量(如果使用了該成員變量 編譯會報錯:實例變量不能在類方法裏被訪問)
7.成員變量是實例的變量 , 類裏面根本就沒有 ,只能被對象訪問

8.能用類方法就用類方法,這樣執行效率高。當方法內部不需要成員變量時,就可以改爲類方法。
9.使用場合:①基本沒有任何成員的類叫做工具類,裏面的方法基本都是類方法②方便在類中 用類相互調用③可以在對象方法裏 調用類的方法

代碼舉例

#import <Foundation/Foundation.h>

@interface Person:NSObject
+ (void) printClassName;
-  (void) test;
@end
@implementation Person 
+ (void) printClassName
{
    NSLog(@“這個類叫做Person”);
}
- (void) test
{
    NSLog(@“這個方法是對象的”);
}
@end
int main()
{
    Person *p=[Person new];
    [Person printClassName];//提高性能 沒創建對象 依然可以調用類的行爲方法 省了對象的內存

    return 0;
}

四、 self的用法

知識點

1.語法:
    1)self 指向當前方法調用者
    2)可以利用“self->成員變量名”訪問當前對象內部的成員變量
    3)[self 方法名]可以調用其他對象方法\類的方法
2.self使用注意
    1)在一個方法裏使用self 調用自己 必會造成死循環
    2)分析代碼 要從self當前指向的東西出發去判斷
    3)函數和方法不一樣 函數不需要[]去調用

代碼舉例

#import<Foundation/Foundation.h>
@interface Person:NSObject
{
    int _age;
}
- (void)setAge:(int) age;
- (int)age;
- (void)test;
- (void)test2;
@end
@implementation Person
- (void)setAge:(int) age
{
    _age=age;//等效於 self->_age=age;
}
- (int)age
{
    return _age;//等效於 self->_age;
}
- (void) test
{
    int _age=33;/*語法上就近輸出它,但是我硬要輸出我的成員變量怎麼辦呢?1)先賦值給一個變量,用這個變量代替輸出 
2)用self指針指向方法調用者  self->_age*/
    NSLog(@“1Person的年齡%d歲”,_age);
}
- (void) test2
{
    [self test];//
    NSLog(@“2Person的年齡%d歲”,_age);
}
@end
int main()
{
    Person *p=[Person new];
    [p setAge:10];
    [p test];
}

五、 面向對象特性之繼承(組合)

知識點

1.類B繼承類A,B就有了A的所有東西,這樣就抽取了重複代碼,建立了類之間的關係
2.子類可以擁有父類中的所有成員變量和方法
3.基本上所有類的根類都是NSObject

注意點

1.如果子類在父類之前聲明和實現 會報錯 因爲編譯器從上到下編譯的 所以父類要定義在子類之前
2.可以在父類的基礎上擴充自己成員變量和方法:
   擴充自己成員變量時 1)不能有和父類有同名的成員變量
所以父類的方法可以只寫聲明不寫實現,實現交給子類(可以不再寫對應聲明)去實現就好了
3.當子類調用方法,首先在自己的類找,找不到再取去父類找,知道最高層類。
4.子類重新實現父類的某個方法,叫做重寫。於是就覆蓋了父類的所有行爲
5.創建子類的時候 子類和父類都已加載到內存了 
6.每個類裏都有一個superclass 指針 用來指向父類
7.isa 和 superclass 指針 都是聲明在NSObject裏的 只有這樣 才能保證 每一個對象一旦創建就有一個isa指針  
每個類一旦創建就有一個superclass指針
8.耦合性太強:類之間關係很緊密 (這使得 刪除一個都導致另一個不能用 弊端)

代碼舉例

#import<Foundation/Foundation.h>
@interface Animal:NSObject
{
    int _age;
    double _weight;
}
- (void) setAge:(int)age;
- (int) age;
- (void) setWeight:(int)weight;
- (int) weight;
@end
@implementation Animal
- (void) setAge:(int)age;
{
    _age=age;
}
- (int) age
{
    return age;
}
- (void) setWeight:(int)weight
{
    _weight=weight;
}
- (int) weight
{
    return _weight
}
@end
//狗
@interface Dog:Animal//Dog類繼承自Animal
@end
@implemetation Dog
@end

//貓
@interface Cat:Animal//繼承了父類Animal所有成員變量和方法
@end
@implemetation Cat
@end
int main()
{
    Dog *d=[Dog new];
    [d setAge:10];//使用了父類的setAge
    NSLog(@“狗的年齡%d”,[d age]);
    return 0;
}

繼承和組合

1.當兩個類擁有相同屬性和方法的時候,就可以將相同的東西抽象到一個父類中
2.當A類擁有B類中的部分屬性和方法中,就可以考慮讓B類繼承A類,同時還得考慮A B類之間存在從屬關係
3.組合 :繼承不成 可以考慮組合 區別:繼承 xx 是 xxx ;組合 xxx擁有xxx
4.學生是個成績 X 學生擁有成績

繼承和組合簡單舉例

A
{

}
B:A//B繼承A
{

}
組合
A
{

}
B
{
   A * _a;//B擁有A
}

六、 面向對象特性之多態

知識點

1.多態講的是 (父類)對象具有(多個子類)多態 (就是多種形態  要想多態 必須有繼承  沒有繼承 沒有多態)
【將多個方法合併成一個方法】
3.侷限性:Animal *aa=[Dog new];  [aa run];//編譯器會檢測Animal是否有run 沒有就會有警告 但是可以運行
(動態檢測出了真實類型)
4.父類類型的變量 不能調用子類特有的方法 ,必須要強制轉換下 轉換到子類類型 
所以 Animal *aa=[Dog new];  [(Dog*)aa run];//強制轉換下 就OK了
5.Dog *dd=aa;//(不合理 動物是狗)可以等效於 Dog *dd=(Dog *)aa;//這樣就合法了

代碼舉例

#import<Foundation/Foundation.h>
@interface Animal:NSObject
- (void) eat;
@end

@implementation Animal
- (void) eat
{
    NSLog(@“吃東西————”);
}
@end

@interface Dog:Animal
@end

@implementation Dog
@end

@interface Cat:Animal
@end

@implementation Cat
- (void) eat
{
    NSLog(@“貓吃東西餓————”);
}
@end
void feed(Dog *d)/*如果也想用這個方法喂貓 直接傳貓對象顯然不合理 那麼怎麼辦呢??1)在寫一樣的方法 形參換下 
2)直接 把形參 改爲 Animal *a */
{
    [d eat];
}
int main()
{
    //多種類型
    Dog *d=[Dog new];//Dog 類型 狗以狗的形態存在
    //多態:父類指針指向子類對象  狗以動物的形態存在
    Animal *a=[Dog new];//OK
    NSObject *n=[Animal new];//OK
    NSObject *n2=[Dog new];//OK 
    [a eat];/*調用的eat是父類的還是子類的呢???真相是調用的是子類的 因爲調用時會自動檢測對象的真實類型 
    顯然這是a指向對象的真實類型是Dog*/

    Cat *c=[Animal new];//動物是貓 但是OC這是弱語法(容錯能力強)所以不會報錯 但有警告 不提倡這樣寫

    NSString *s=[Car new];//貓是字符串 但是OC這是弱語法 所以不會報錯 但有警告 不提倡這樣寫 
    feed(d);
}

七、 學習查缺補漏

1.super關鍵字作用

 1.1.直接調用父類中的某個方法
 1.2.super處在對象方法中,那麼就會調用父類的對象方法
     super處在類方法中,那麼就會調用父類的類方法
 1.3.使用場合:子類重寫父類的方法時想保留父類的一些行爲
#import <Foundation/Foundation.h>

// 殭屍
@interface Zoombie : NSObject
- (void)walk;

+ (void)test;
- (void)test;

@end

@implementation Zoombie
- (void)walk
{
    NSLog(@"往前挪兩步******");
}

+ (void)test
{
    NSLog(@"Zoombie+test");
}

- (void)test
{
    NSLog(@"Zoombie-test");
}
@end

// 跳躍殭屍
@interface JumpZoombie : Zoombie
+ (void)haha;
- (void)haha2;
@end


@implementation JumpZoombie

+ (void)haha
{
    [super test];
}

- (void)haha2
{
    [super test];
}

- (void)walk
{
    // 跳兩下
    NSLog(@"跳兩下");

    // 走兩下(直接調用父類的walk方法)
    [super walk];
    //NSLog(@"往前挪兩步----");

}
@end

int main()
{
    //[JumpZoombie haha];
    JumpZoombie *jz = [JumpZoombie new];

    [jz haha2];

    return 0;
}

2.NSString的使用

2.1.@“ddddddd”就是一個NSString類對象
2.2.NSString *str=@“dddd”;//好處 以面向對象的形式處理字符串 獲取長度 int size =[str length]; 
2.3.[str length]返回的是unsigned long 類型的 統計的是字數(包括空格)不是字符數了  一個漢字 一個字母 就是2個
2.4.char *str=“dddd”;//不建議使用

代碼舉例

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    //char *_name;
    NSString *_name;
}
@end

int main()
{
    /*
    // 最簡單的創建字符串的方式
    NSString *str = @"iloveios";

    char *name = "iloveios";


    NSLog(@"我在%@寫代碼", str);
    //NSLog(@"%s", name);
    */

    int age = 15;
    int no = 5;
    NSString *name = @"哈哈jack";
    // length方法算的是字數
    int size = [name length];

    NSLog(@"%d", size);

    // 創建OC字符串的另一種方式
    NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d 
    and name is %@", age, no, name];


    NSLog(@"---- %ld", [newStr length]);

    return 0;
}
發佈了36 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章