iOS9 with Swift 傘型

傘型(Umbrella Type):

Swift提供了不少內置類型來作為替班傘型,它們能夠在一個標頭下包含多個實際類型。

AnyObject:

在實際編程匯總最常見的傘型就是AnyObject。它其實就是一個協議;它里面是全空的,沒有要求任何的屬性和方法。它有一個特性:所有的類都會自動采用它。因此在需要AnyObject的地方,任何類的實例都是可以被傳遞或者賦值的,還可以進行轉型(cast)

1

有的不是類的Swift類型,比如String和其他基本數字類型,可以橋接到是類的Oc類型上(被Foundation框架定義)。這就意味著,如果有Foundation框架,這些可以橋接的Swift類型就可以被分配、傳遞和轉型給AnyObject,即使它不是類。因為在后臺它會先被自動轉換成Oc的類。而且AnyObejct可以被向下轉型為Swift的橋接類型,比如:


2

遇到AnyObject的常見方法就是與Oc相互轉換的過程。Swift向上向下轉換AnyObject的方法和Oc向上向下轉換id是一樣的。實際上,AnyObject就是Swift版的id。

NSUserDefaults, NSCoding, and key–value coding都允許你通過String類型的關鍵名不確定的類中取出對象,這樣的對象到了Swift中就是AnyObject,更準確的說是可選值包著的AnyObject,因為很有可能沒有這個key,而這種情況Cocoa會返回nil值。一般地,AnyObject對你沒什么用;你想的是要Swift知道具體是什么值,解包和轉型是由你來決定的。如果你很確定,那么可以用強制解包和強制轉型as!


3

抑制類型檢查:

AnyObject還可以推遲編譯器對特定消息可不可發送給對象的檢查機制,類似于Oc的輸入id可以推遲編譯器檢查什么消息可以被發送給id。因此你可以在沒有將AnyObject轉為特定類型的情況下,發送消息給它。(不過如果你知道對象的真實類型,還是盡早轉型吧)

你不能僅僅發送老舊的消息給AnyObject;這些消息必須相符于滿足下面標準之一的類型成員:

1、它是Oc的一個類的成員。

2、它是你創建的 Oc類的子類(或者擴展)的成員。

3、它是Swift類,而且被標記為@objc(或者dynamic)

這個特性基本上與可選的協議成員是類似的,雖然有一點小小的差別,讓我們從兩個類開始:


4

Dog的noise屬性和bark方法被標記為@objc,所以它們作為潛在消息是對發送給AnyObject可見的。為了驗證這個,我將Cat定義為AnyObject再向它發送該消息,先從noise開始:


5

這段代碼竟然編譯了!此外還可以運行!noise屬性是被當做可選值包著的其原始類型輸入的。而在這里它是可選值中包著String (Dog實現)。如果被聲明為AnyObject的沒有實現noise,那么它就會無害的返回nil。此外不像可選協議屬性,該可選值會被隱式解包。因此如果AnyObject是實現了noise屬性的類型(比如Dog),結果就是String。

現在再試試調用方法。


6


如上,如果該類型沒有實現noise,那么將會返回nil,如果實現了結果就是可選值包著的String。使用bark!( ),結果是String,但是如果沒有實現,那么程序就會崩潰。不像可選協議成員,你可以直接發送不解包的消息,這樣和!強制解包效果是一樣的:


7

對象身份和類型身份:

有時,我們想知道的不是一個對象的類型是什么,而是這個對象是不是我們想的那個特定的對象。這個問題不會出現在值類型上,而會出現在引用類型上。可能類是引用類型,所以這個問題會出現在類的實例上。

Swift使用===運算符來解決這個問題。===可以被采用了AnyObject協議的對象類型實例使用,比如類。它不是像==那樣比較值是不是相等,它是檢驗兩個對象是不是引用同一個對象。它的否定形式是!==

一個典型的使用場景就是Cocoa中的類的實例,你想知道它是不是你所引用的對象。比如:NSNotification有一個object屬性來幫助識別notification(usually, it is the original sender of the notification)。Cocoa不知道它的下級類型,這是另一個你將得到可選值包著Anyobject的情況。就像==,===也可以自動解包的,所以你就可以用它來確定object就是你想要的對象了。


8

AnyClass:

AnyClass是AnyObject的類型。它相當于Oc中的Class類型,當Cocoa API想要說需要一個class,就會出現在其聲明中了。

比如,UIView的layerClass類方法用Swift的方法聲明時:


9

這意味著:如果你重寫該方法,會返回一個類。這大概是CALayer的子類。為了在實現中返回一個確切的類,把self消息發送給該類:


10


AnyClass對象的引用和AnyObject對象的引用很相似。你可以發送任何Swift知道的Oc消息,比如任何的Oc的類消息。


11

Oc可以看到whatDogSays,并把它看做類類屬性。因此你可以發送whatDogSays給AnyClass的引用。


12

類型的引用變量(你可以通過發送dynamicType消息給其實例來獲得其類型,或者通過其類型名后面加self來獲得)的類型采用了AnyClass,你可以使用===來比較不同引用:


13

如果d和whattype是一樣的類型,這個就是true(這里不支持多態)。比如。Dog有個NoisyDog子類,如果參數分別是Dog( ) Dog.self ,或者 NoisyDog( ) NoisyDog.self,就是true。但是如果是 NoisyDog( ) Dog.self 就是正確的。

即使沒有多態,這也是很有價值的。因為當在后面的是類本身的引用時,你不能用is運算符。

Any:

Any是一個被所有類型采用的空協議的別名。因此,可以用Any的地方,所以類型都能用。


14

一個Any類型的對象可以被檢驗、轉型到任何對象和函數類型。為了說明,這里有一個有關聯類型的協議,還有兩個顯式決定其類型的采用者。


15

現在這個函數需要兩個參數:一個是Flier 一個是Any。檢驗第二個參數類型是不是和第一個參數的Other一樣,這是合法的,因為Any可以和任何的類型的檢驗。


16

如果我調用Bird和Insect為兩個參數,那么就會顯示they can flocktogether。如果我調用其中之一和另一種不是這兩個的類型,就不會輸出了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Swift 介紹 簡介 Swift 語言由蘋果公司在 2014 年推出,用來撰寫 OS X 和 iOS 應用程序 ...
    大L君閱讀 3,271評論 3 25
  • 集合類型: Swift,和其他現代編程語言一樣,有內置的集合類型數組(Array)和字典(Dictionary),...
    小松樹先生閱讀 1,118評論 0 2
  • 概述 利用runtime特性實現iOS項目的組件化開發,是由@casatwy大神提出來的,在他的博客中具體介紹...
    Mr杰杰閱讀 1,626評論 2 9
  • 一直沒有時間好好看一下swift,最近復習了一遍語法,這里記錄swift學習過程中遇到的一些問題和要點,和Obje...
    bomo閱讀 2,393評論 0 25
  • 我一邊拒絕一邊想象 想象冬天之前的那個春天 我們像個孩子似的愛的瘋狂 桃紅杏白, 我的心卻在默哀 祭奠我逝去的摯愛...
    心心稀語閱讀 257評論 0 0