iOS提供指定構造器

2021-09-24 07:06:33 字數 2390 閱讀 8288

如果自己編寫框架或者檢視開源框架的一些初始化介面,或多或少都會發現,一般框架都會提供非常豐富便利的初始化介面,這些初始化介面的背後都會集中呼叫某個核心的初始化方法。 ios的uikit中的類,大多都會有乙個核心的初始化方法或者稱為指定構造器,比如uiview- (instancetype)initwithframe:(cgrect)frame,uiviewcontroller- (instancetype)initwithnibname:(nullable nsstring *)nibnameornil bundle:(nullable nsbundle *)nibbundleornil這樣做的好處是,可以使類的初始化方法看起來簡單明瞭,減少**量,方便維護初始化介面,當類發生一些改變的時候,只需要更改核心初始化方法

另外提供指定的構造器可以為屬性或者例項變數提供預設值,讓類在初始化的時候每個屬性都有合適的初始值,不至於是nil或者0,這樣可以避免一些錯誤,更加安全。比如如果提供了乙個陣列屬性,**寫了很多,最後除錯的時候不知道**出錯,最後發現陣列沒有初始化或懶載入。

《effective object-c 2.0》 第16條 就有建議提供指定初始化方法;相對於swift的構造語法,object-c初始化語法有點寬鬆,同時也帶來很多問題,拿《effective object-c 2.0》上的例子來說:

// eocrectangle.h

@inte***ce eocrectangle : nsobject

@property (nonatomic, assign, readonly) float width;

@property (nonatomic, assign, readonly) float height;

@end

// eocrectangle.m

- (instancetype)initwithwidth: (float)width andheight: (float)height

return self;

}複製**

1.由於object-c會繼承父類的初始化方法,所有繼承nsobject的類都有init的這個方法,為了防止開發者沒有使用指定初始化方法還必須要重寫這個方法,uikit中大多數類也重寫了這個方法,拿上面的uiviewuiviewcontroller來說,如果直接使用init方法建立例項,底層還是會呼叫對應的指定初始化方法,拿上面的例子來說,如果要想使類變得完善,還需要處理繼承父類的init方法;《effective object-c 2.0》中提供了兩種方式來處理,個人覺得這兩種方式都不能說優雅

- (instancetype)init

複製**

如果不進行說明,還要檢視源**才知道預設值,這種方式如果指定初始化方法做出修改,模擬較簡單還好控制,初始化方法比較複雜就會讓事情變得複雜

- (instancetype)init

複製**

這種方式就更加是無奈之舉,雖然安全性是有了保障,但是這是根本上違背了異常設計的初衷,我很難把呼叫這個方法想象成致命的錯誤

2.如果這時候再來乙個繼承類的話,由於初始化方法的繼承又會使事情變得糟糕,詳情可以參考《effective object-c 2.0》第16條

總結:1.盡可能的為類提供指定初始化方法,在初始化方法中為屬性提供合適的初始值

2.寫好指定初始化方法之後,處理繼承父類的初始化方法,如果父類的初始化方法不適用與子類,重寫父類的初始化方法並丟擲異常。

swift構造器的規則在這方面就顯得非常現代化和安全,對於上面的問題,swift都有明確的規則進行限定(雖然swift的構造過程規則較多,理解之後使得構造邏輯非常清晰也變得簡單)

明確了指定構造器和便利構造器而且便利構造器還有關鍵字標明,甚至明確便利構造器的呼叫鏈的最後必須呼叫到同一類的指定構造器

類中的所有儲存型屬性必須在構造過程中設定初始值,swift的兩段式構造過程還提供了構造過程的安全檢查,使**更加安全

swift中的子類不會預設繼承父類的構造器(滿足一定條件繼承父類的構造器,實際上還是為新引入的儲存屬性提供了預設的初始值,這樣也簡化了構造器的編寫)

對於上面的例子swift就變得簡單的多

class rectangle: nsobject 

}class square: rectangle

}複製**

對於rectangle,它提供了指定構造器也就不會繼承nsobject的構造方法,你也只能使用指定構造器來例項化rectangle

對於square也一樣,不用像object-c一樣來處理繼承的父類的構造方法

構造器 二 指定構造器 便利構造器

在swift中類一共有兩種構造器 我個人的理解為在類中沒有加任何關鍵字的構造器稱為指定構造器,作用為初始化類中所有的例項儲存屬性 init 我個人理解為在類中 只能在類中,結構體和列舉裡面是沒有的 加上convenience關鍵字的構造器為便利構造器,作用為輔助性呼叫指定構造器進行一系列的工作。感覺...

構造器 二 指定構造器 便利構造器

在swift中類一共同擁有兩種構造器 我個人的理解為在類中沒有加不論什麼keyword的構造器稱為指定構造器。作用為初始化類中全部的例項儲存屬性 init 我個人理解為在類中 僅僅能在類中,結構體和列舉裡面是沒有的 加上conveniencekeyword的構造器為便利構造器,作用為輔助性呼叫指定構...

C 編譯器何時提供預設的建構函式和拷貝建構函式

2008年08月27日 星期三 10 16 總的來說,編譯器只在它需要的時候才會合成乙個預設建構函式,或者擴張所有已存在的建構函式。乙個類滿足下列其中任何乙個條件 1.包含了乙個類的物件,這個物件有乙個建構函式 包括編譯器合成的預設建構函式 2.如果繼承自一些基類,其中某些基類有乙個建構函式 包括編...