Swift 中的類(lèi)型
本文主要介紹Swift
中的元類(lèi)型饺律,其中包含AnyObject
、Any
跺株、AnyClass
复濒、T.Self
、T.Type
乒省、以及type(of:)
巧颈。
1. AnyObject
Swift
中的AnyObject
代表任意的instance
、類(lèi)的類(lèi)型袖扛、僅類(lèi)遵守的協(xié)議砸泛,下面我們通過(guò)一些例子來(lái)解釋這句話。
class Person {
var age = 19
}
var p1: AnyObject = Person()
var p2: AnyObject = Person.self
以上就是實(shí)例對(duì)象和類(lèi)的類(lèi)型蛆封,都可以用AnyObject
表示唇礁。
protocol JsonMap: AnyObject { }
struct StructMap: JsonMap { }
class ClassMap: JsonMap { }
我們可以看到,在結(jié)構(gòu)體中遵守JsonMap
協(xié)議的時(shí)候會(huì)報(bào)編譯錯(cuò)誤Non-class type 'StructMap' cannot conform to class protocol 'JsonMap'
惨篱,StructMap
不是class
類(lèi)型盏筐,不能遵守JsonMap
這個(gè)類(lèi)類(lèi)型的協(xié)議。
當(dāng)然我們?cè)?code>OC和Swift
交互的時(shí)候砸讳,AnyObject
也能表示OC
中的類(lèi)類(lèi)型琢融,例如:
var n: AnyObject = 10 as NSNumbers
2. Any
Swift
中的Any
代表任意類(lèi)型界牡,是比AnyObject
更加廣泛的類(lèi)型,除了AnyObject
包含的類(lèi)型漾抬,其還包括funcation
類(lèi)型或者Optional
類(lèi)型宿亡,以及一些基本類(lèi)型和字面量。
舉個(gè)例子纳令,一個(gè)不固定類(lèi)型的數(shù)組挽荠,就可以用Any
進(jìn)行表示,如果使用AnyObject
就會(huì)報(bào)錯(cuò):
var array: [Any] = [1, "swift", "", true]
3. AnyClass
Swift
中的AnyClass
代表任意實(shí)例類(lèi)型平绩,也就是AnyObject.Type
圈匆。
我們可以查看其定義:
public typealias AnyClass = AnyObject.Type
簡(jiǎn)單的說(shuō),所有的類(lèi)都是AnyClass
類(lèi)型
4. T.self
如果T
是實(shí)例對(duì)象馒过,則T.self
就是實(shí)例對(duì)象本身
如果T
是類(lèi)臭脓,則T.self
就是MetaData
舉個(gè)例子:
var p = Person()
//實(shí)例對(duì)象地址:實(shí)例對(duì)象.self 返回實(shí)例對(duì)象本身
var p1 = p.self
//存儲(chǔ)metadata元類(lèi)型
var p2 = Person.self
通過(guò)lldb打印
通過(guò)上面的兩幅圖我們可以看到酗钞,實(shí)例對(duì)象.self
返回的就是實(shí)例對(duì)象腹忽,類(lèi).self
返回的是類(lèi).Type
的實(shí)例,內(nèi)部存儲(chǔ)著metaData
砚作。也可以理解為存儲(chǔ)著metadata
4. T.Type
- 對(duì)于
T.Type
實(shí)際上是一種類(lèi)型 -
T.self
是T.Type
類(lèi)型窘奏,這個(gè)在類(lèi).self
返回的是類(lèi).Type
的實(shí)例中即可證明。
5. type(of:)
在Swift
中type(of:)
是一個(gè)用來(lái)獲取值的動(dòng)態(tài)類(lèi)型的方法葫录。同時(shí)對(duì)于oc
中的類(lèi)型也可以獲取到着裹。下面我們通過(guò)一些實(shí)例來(lái)演示一下。
demo1:
var a = 10 as NSNumber
var b = 10
//func printType(_ value: Any) {
// print(type(of: value))
//}
//printType(a)
//printType(b)
print(type(of: a))
print(type(of: b))
打印結(jié)果:
demo2:
class Person {
var age = 19
func eat() {
print("Person eat")
}
}
class YellowPerson: Person {
override func eat() {
print("YellowPerson eat")
}
}
func printType(_ value: Person) {
let valueType = type(of: value)
value.eat()
print(valueType)
}
var p = YellowPerson()
printType(p)
打印結(jié)果:
這里我們發(fā)現(xiàn)雖然在printType
方法中的參數(shù)我們使用的是Person
類(lèi)型米同,但是打印的類(lèi)型依舊就是實(shí)例對(duì)象的類(lèi)型YellowPerson
骇扇。對(duì)于方法調(diào)用的是子類(lèi)的方法也沒(méi)什么說(shuō)的,子類(lèi)肯定優(yōu)先調(diào)用子類(lèi)重寫(xiě)的父類(lèi)的方法面粮。
demo3:
protocol TestProtocol {
}
class Person: TestProtocol {
var age = 19
func eat() {
print("Person eat")
}
}
func printType(_ value: TestProtocol) {
let valueType = type(of: value)
print(valueType)
}
var p1 = Person()
var p2: TestProtocol = Person()
printType(p1)
printType(p2)
打印結(jié)果:
此時(shí)我們可以看到在使用協(xié)議后少孝,打印的類(lèi)型依舊是Person
,因?yàn)閷?duì)象始終的Person
類(lèi)的實(shí)例對(duì)象熬苍。在swift
中協(xié)議中是沒(méi)有屬性的稍走,并且協(xié)議的使用一般都依附于類(lèi)和結(jié)構(gòu)體,所以此處獲取到類(lèi)的類(lèi)型也是符合需求的柴底。
demo4:
如果將demo3
中printType
方法修改成如下婿脸,即使用泛型:
func printType<T>(_ value: T){
let valueType = type(of: value)
print(valueType)
}
打印結(jié)果:
此時(shí)我們發(fā)現(xiàn)居然打印了TestProtocol
,原因是因?yàn)橛袇f(xié)議和泛型時(shí)柄驻,編譯器并不能推斷出準(zhǔn)確的類(lèi)型狐树,需要將value
強(qiáng)轉(zhuǎn)為Any
,修改代碼為如下:
func printType<T>(_ value: T){
let valueType = type(of: value as Any)
print(valueType)
}
打印結(jié)果: