標籤:style java color 使用 檔案 資料 io 問題
接觸物件導向也有一段時間了,當時是通過C++學習的OOP,後來又接觸到了PHP和Java。每種OOP的語言在物件導向上或多或少都會有不同的地方,現在在學習OC的物件導向部分,又感覺到OC物件導向的特點。寫篇博文總結一下OC中的物件導向。剛接觸OC,用OC中的便利初始化方法和便利構造器有點蹩腳,不過還可以在接受的範圍之內,以下的東西可能會對物件導向的特徵:抽象,封裝,繼承等總結的較少一些,主要總結了OC中物件導向的特點。在用到便利構造器的時候,如果之前學習過設計模式的話會好理解一些。
在下面的代碼執行個體當中,可能在便利初始化方法和便利構造器這一塊理解起來有些問題。簡單的說來,便利構造器是為了簡化對象的初始化而生的,在之前的部落格中也說了一嘴:編程是間接的過程,其實使用便利構造器就是間接的過程。在程式中處處都用到了間接。比如你定義的變數,你定義的函數,都是在間接的使用一些東西。在現實生活中間接的作用的很大的,就連找個女朋友也要間接一下,如果間接好了你很有可能和奧巴馬成為好哥們不是嗎,不是有種理論叫做六度人脈嗎?程式中的間接的好處是什麼呢?
根據個人的理解,間接原則會讓自己寫的代碼更為靈活,會避免一些不必要的重複編寫代碼。函數就是一個最好的例子,把程式中不變且常用的部分進行封裝,然後把變的部分用函數的參數列表傳進來,這樣就很好的實現代碼的重用功能,這也是函數存在編程中的意義所在。偽文藝一下,哲學上不是有句話叫做世界上每種存在的事物都有他存在的意義。達爾文的適者生存論放在電腦技術發展中也是挺適用的,能被保留的東西一定會有他的作用。
言歸正傳,便利構造器就是對便利初始化函數的間接使用,目的是為了簡化對象的初始化(這裡是我個人的理解)。便利初始化函數(對象方法)的作用是給執行個體常量賦初值,在類的執行個體化後就可以調用便利初始化函數了。而便利構造器是類方法,返回的是對象,在便利構造器中做了兩件事:一個是給對象分配空間,第二個是調用便利初始化函數進行資料的初始化。學過設計模式的小夥伴都應該知道“模板方法模式”,我個人感覺便利構造器和模板方法模式的作用挺相似的。
以下的東西是依附於代碼來講解的,編程嗎,即使講思想也少不了代碼不是嗎,話不多說,切入正題。請大家批評指正,若要轉載請註明出處。
物件導向程式開發的主要目標:用代碼類比現實中的對象,將現實中對象的某些行為能力,特徵用代碼錶現出來,然後用這些代碼來類比現實中的問題。
每個對象都會從兩個角度進行描述,一個是特徵,一個是行為能力
特徵:可以是物體的組成部分,也可以是一些物理或邏輯上的屬性,用來表現對象的形態,構成及狀態。
行為能力:對象所能被進行的操作或者物體本身發起的操作。用來接受外部操作或對外部進行操作。
封裝:將屬性及方法相結合,共同體現對象的特徵,稱之為封裝,封裝可以實現隱藏內部實現,穩定外部介面。
在OC中類是由介面(interface)和實現(implementation)兩部分構成的。在OC中類是通過兩個單獨的檔案定義。介面定義在對應的標頭檔中,該檔案的作用是說明此類具有哪些屬性和方法,但不去實現其行為。
1. OC中介面的定義如下:
1234567891011121314151617181920 |
#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.在介面中方法只有聲明,沒有實現,方法前面的減號代表此方法是對象方法,如果是+號的話,說明是類方法,就是說類可以直接存取此方法。
[email protected] 和 @end是成對出現的,@end代表介面定義的結束
6.上面得成員變數定義成了公有的,這在開發中是極少見的,這裡為了方便練習才這麼寫的,一般把成員變數定義為私人的然後在定義get,set方法去操作成員變數
這樣才起到了封裝,不要把自己的手直接伸入到類中,要通過類提供的方法來操作類的成員變數。
[email protected] 實現部分
實現部分檔案的副檔名為.m,具體實現的方法代碼如下:
12345678910111213141516 |
#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來聲明類方法的實現
[email protected]和@end也是成對出現的
代碼規範:
1.類名的首字母要大寫
2.方法的命名使用駝峰命名法
3.建立和使用對象
定義了一個類,一般需要執行個體化才能使用,當然靜態類是不需要執行個體化就能用的。對象是類的實體,類是對象的抽象,因此需要對類進行執行個體化。
執行個體化的代碼如下:
123456789101112131415161718192021222324 |
#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->[email protected] "愛咋咋地" ; //調用成員方法 [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中的建構函式,重寫代碼如下:
1234567891011 |
//重寫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中進行重新的代碼如下:
123456789101112131415161718 |
//實現便利初始化方法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中定義參數的方式是: (參數類型)參數名 第二個參數別名:(參數類型)參數名
? ? ? ?2.只要便利初始化方法符合函數重載的條件,是可以重載的
? ?使用便利初始化方法來進行對象的初始化,代碼如下:
123 |
//調用便利初始化方法 Student *s1 = [[Student alloc] initWithName:@ "dashi1" iAge:19]; [s1 sayHello]; |
?3.便利構造器
?上面用便利初始化方法在類執行個體化時有些繁瑣,為了簡化執行個體化的操作,自訂一個類方法,類方法的作用是進行類的執行個體化同時進行參數的初始化,並返回對象
? ?便利構造器的實現代碼如下:
123456 |
//實現便利構造器,進行類的執行個體化並調用initWithName + (id) studentWithName:(NSString *)name age:( int )sAge { Student *student = [[Student alloc] initWithName:name iAge:sAge]; return student; } |
?
? ?便利構造器的使用如下:
12 |
//調用便利構造器初始化對象 Student *s2 = [Student studentWithName:@ "dashi2" age:20]; |
? ? ? ?