close
文章出處

  接觸面向對象也有一段時間了,當時是通過C++學習的OOP,后來又接觸到了PHP和Java。每種OOP的語言在面向對象上或多或少都會有不同的地方,現在在學習OC的面向對象部分,又感覺到OC面向對象的特點。寫篇博文總結一下OC中的面向對象。剛接觸OC,用OC中的便利初始化方法和便利構造器有點蹩腳,不過還可以在接受的范圍之內,以下的東西可能會對面向對象的特征:抽象,封裝,繼承等總結的較少一些,主要總結了OC中面向對象的特點。在用到便利構造器的時候,如果之前學習過設計模式的話會好理解一些。

  在下面的代碼實例當中,可能在便利初始化方法和便利構造器這一塊理解起來有些問題。簡單的說來,便利構造器是為了簡化對象的初始化而生的,在之前的博客中也說了一嘴:編程是間接的過程,其實使用便利構造器就是間接的過程。在程序中處處都用到了間接。比如你定義的變量,你定義的函數,都是在間接的使用一些東西。在現實生活中間接的作用的很大的,就連找個女朋友也要間接一下,如果間接好了你很有可能和奧巴馬成為好哥們不是嗎,不是有種理論叫做六度人脈嗎?程序中的間接的好處是什么呢?

  根據個人的理解,間接原則會讓自己寫的代碼更為靈活,會避免一些不必要的重復編寫代碼。函數就是一個最好的例子,把程序中不變且常用的部分進行封裝,然后把變的部分用函數的參數列表傳進來,這樣就很好的實現代碼的重用功能,這也是函數存在編程中的意義所在。偽文藝一下,哲學上不是有句話叫做世界上每種存在的事物都有他存在的意義。達爾文的適者生存論放在計算機技術發展中也是挺適用的,能被保留的東西一定會有他的作用。

  言歸正傳,便利構造器就是對便利初始化函數的間接使用,目的是為了簡化對象的初始化(這里是我個人的理解)。便利初始化函數(對象方法)的作用是給實例常量賦初值,在類的實例化后就可以調用便利初始化函數了。而便利構造器是類方法,返回的是對象,在便利構造器中做了兩件事:一個是給對象分配空間,第二個是調用便利初始化函數進行數據的初始化。學過設計模式的小伙伴都應該知道“模板方法模式”,我個人感覺便利構造器和模板方法模式的作用挺相似的。

  以下的東西是依附于代碼來講解的,編程嗎,即使講思想也少不了代碼不是嗎,話不多說,切入正題。請大家批評指正,若要轉載請注明出處。

  面向對象程序開發的主要目標:用代碼模擬現實中的對象,將現實中對象的某些行為能力,特征用代碼表現出來,然后用這些代碼來模擬現實中的問題。

  每個對象都會從兩個角度進行描述,一個是特征,一個是行為能力

            特征:可以是物體的組成部分,也可以是一些物理或邏輯上的屬性,用來表現對象的形態,構成及狀態。

            行為能力:對象所能被進行的操作或者物體本身發起的操作。用來接受外部操作或對外部進行操作。

    封裝:將屬性及方法相結合,共同體現對象的特征,稱之為封裝,封裝可以實現隱藏內部實現,穩定外部接口。

   

    在OC中類是由接口(interface)和實現(implementation)兩部分構成的。在OC中類是通過兩個單獨的文件定義。接口定義在對應的頭文件中,該文件的作用是說明此類具有哪些屬性和方法,但不去實現其行為。

       

        1. OC中接口的定義如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#import <Foundation/Foundation.h>
 
@interface Student : NSObject
{//大括號里定義屬性
    //定義學生的學號,姓名,年齡,愛好;
    @public
    NSString *studentName;
    int age;
    NSString *hobby;
}
 
/*定義學生有關的方法,+修飾的為類方法,不用實例化就可以直接用類訪問
* -號修飾的為對象方法,必須實例化后才能使用,就是用對象調用的方法
*/
 
//定義打招呼的方法
- (void) sayHello;
//吃飯行為
- (void) eat;
@end

 

        代碼說明:

            1.#import<Foundation/Foundation.h>語句告訴編譯器查看Foundation框架中的Foundation.h的頭文件

            2.用#import指令來導入相應的文件,#import的作用相當于PHP中的require_once,如果文件之前導入過了,則不導入,而#include會重復導入文件的

            3.用編譯器指令@interface來定義類的聲明,@interface后面是類名,Student : NSObject 說明Student繼承于NSObject類

            4.在接口中方法只有聲明,沒有實現,方法前面的減號代表此方法是對象方法,如果是+號的話,說明是類方法,就是說類可以直接訪問此方法。

            5.@interface 和 @end是成對出現的,@end代表接口定義的結束

            6.上面得成員變量定義成了公有的,這在開發中是極少見的,這里為了方便練習才這么寫的,一般把成員變量定義為私有的然后在定義get,set方法去操作成員變量

      這樣才起到了封裝,不要把自己的手直接伸入到類中,要通過類提供的方法來操作類的成員變量。

 

 

        2.@implementation 實現部分

            實現部分文件的擴展名為.m,具體實現的方法代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import "Student.h"
 
@implementation Student
//實現打招呼的行為
- (void) sayHello
{
    NSLog(@"hello! 我是%@, 我今年%d歲了, 我喜歡%@!", studentName, age, hobby);
}
 
//實現吃飯行為
- (void) eat
{
    NSLog(@"%@也得吃飯呢!",studentName);
}
 
@end

         代碼說明:

                  1.在實現文件中首先導入對應的類的接口文件#import "Student.h",引入系統文件用<FileName>, 引入自定義文件用“FileName”;

                  2.用編譯器指令@implementation來聲明類方法的實現

                  3.@implementation和@end也是成對出現的

         代碼規范:

                1.類名的首字母要大寫

                2.方法的命名使用駝峰命名法

 

    3.創建和使用對象

        定義了一個類,一般需要實例化才能使用,當然靜態類是不需要實例化就能用的。對象是類的實體,類是對象的抽象,因此需要對類進行實例化。

        實例化的代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#import <Foundation/Foundation.h>
 
//引入定義的類
#import "Student.h"
 
int main(int argc, const char * argv[])
{
 
    @autoreleasepool {
        //創建對象,完成對象的聲明,內存分配,初始化
        Student *student = [[Student alloc] init];
         
        //為了方便,在這就直接給成員變量賦值,前提是成員變量是公有的
        student->studentName = @"ludashi";
        student->age = 20;
        student->hobby=@"愛咋咋地";
         
        //調用成員方法
        [student sayHello];
        [student eat];
         
    }
    return 0;
}

        

    ​    ​  代碼說明:

    ​    ​    ​    ​1.要在一個類中實例化類,首先要引入類的接口定義文件如上面的 #import “Student.h”;

    ​    ​    ​    ​2.OC中類的實例化方式是 Student  *student =  [[Student alloc] init], 可以理解為Student類在NSObject類中繼承了alloc方法, alloc這個方法是用來

       實例化對象的 ​init 是默認的構造方法

    ​    ​    ​    ​3.在OC中對象調用其中的方法是通過[]來實現的,[對象名   方法名];

    ​    ​  定義對象的語法:

    ​    ​    ​    ​類名    ​*對象名 = [  [ 類名 alloc ] init ];   或者

    ​    ​    ​    ​類名    ​*對象名 = [ 類名  new];

    ​    ​  給對象的成員變量賦值和調用對象的方法如下:

    ​    ​    ​    ​對象名->成員變量名 = 具體值;

    ​    ​    ​    ​[ 對象名 方法名];

 

    ​一:類方法和對象方法

    ​    ​上面也提到了,減號開頭的方法為對象方法,需要實例化類后通過對象來進行調用。對象方法允許調用對象方法和對象變量​加號開頭的方法為類方法,通過類就可以直接調用的方法。

    ​    ​下面是一些方法調用的一些規則:

    ​    ​    ​    ​1.類方法可以調用類方法;

    ​    ​    ​    ​2.類方法不可以調用對象方法;

    ​    ​    ​    ​3.類方法不可以使用對象變量,類方法可以使用self(self相當于java中的this);    ​    ​    ​

    ​    ​    ​    ​4.可以通過類來調用類方法,但對象不可以調用類方法

    ​    ​

    ​    ​1.對象的初始化

    ​    ​    ​    ​可以重寫父類中的方法init來進行對象的初始化,就相當于Java中的構造函數,重寫代碼如下:

1
2
3
4
5
6
7
8
9
10
11
//重寫init方法,為本類添加構造方法
-(id) init
{
    if (self =[super init])
    {
        studentName = @"dashi";
        age = 18;
        hobby = @"hehe";
    }
    return self;
}

    ​    ​    ​ 代碼說明:

    ​    ​    ​    ​    ​1.因為init是繼承過來的方法因此不需要在interface里面聲明,直接在implementation中進行重寫就OK了;

    ​    ​    ​    ​    ​2. init的返回類型為id, id是OC中的一切父類.在面向對象中父類可以聲明子類的變量

    ​    ​    ​    ​    ​3.[super init]是為了初始化父類的成員變量,返回值為子類對象,如果返回nil,說明父類沒有alloc成功,即不能在alloc子類對象。

 

    ​    ​2.便利初始化函數

    ​    ​    ​自定義的便利初始化函數的作用是讓用戶自己初始化用戶所實例化的對象,便利初始化函數以init開頭,我們可以在類中自定義便利初始化函數。因為便利初始化函數是自  己。  ​定義的所以需要在@interface中進行聲明,便利初始化函數可以進行重載

    ​    ​    ​在@implementation中進行重新的代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//實現便利初始化方法1
- (id) initWithName:(NSString *)sName iAge:(int)anAge
{
    if (self = [super init]) {
        studentName = [sName copy];
        age = anAge;
    }
    return self;
}
 
//實現便利初始化方法2
- (id) initWithName:(NSString *)sName
{
    if (self = [super init]) {
        studentName = [sName copy];
    }
    return self;
}

    ​    ​  代碼說明:

    ​    ​    ​    ​1.函數名后面的冒號跟的是參數列表,在OC中定義參數的方式是: (參數類型)參數名    第二個參數別名:(參數類型)參數名   

    ​    ​   

    ​    ​使用便利初始化方法來進行對象的初始化,代碼如下:

1
2
3
//調用便利初始化方法
Student *s1 = [[Student alloc] initWithName:@"dashi1" iAge:19];
[s1 sayHello];

 

 

    ​3.便利構造器

        ​上面用便利初始化方法在類實例化時有些繁瑣,為了簡化實例化的操作,自定義一個類方法,類方法的作用是進行類的實例化同時進行參數的初始化,并返回對象

    ​    ​便利構造器的實現代碼如下:

1
2
3
4
5
6
//實現便利構造器,進行類的實例化并調用initWithName
+ (id) studentWithName:(NSString *)name age:(int)sAge
{
    Student *student = [[Student alloc] initWithName:name iAge:sAge];
    return student;
}

    ​

    ​    ​便利構造器的使用如下:

1
2
//調用便利構造器初始化對象
Student *s2 = [Student studentWithName:@"dashi2" age:20];

​ ​    ​    ​  

 


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 AutoPoster 的頭像
    AutoPoster

    互聯網 - 大數據

    AutoPoster 發表在 痞客邦 留言(0) 人氣()