/*
今天為止,我們終于把swift中大部分的數(shù)據(jù)類型都給細(xì)細(xì)的學(xué)習(xí)了一遍。也寫了很多很多的測試代碼,相信大家對swift應(yīng)該有了全新的認(rèn)識。接下來我們繼續(xù)學(xué)習(xí)swift語言的一些特性。
本節(jié)呢,我們來學(xué)習(xí) 類型定義和類型投射等操作
在本節(jié)中,我們也能領(lǐng)略swift編程語言的動態(tài)特性。
*/
主要內(nèi)容總結(jié):
1 類型定義 typealias ;
2 元類型 Type;
3 類型獲取 type(of:);
4 Any與AnyObject
5 類型投射 as? as!
6 類型檢查 is
7 嵌套類型
// 1.類型定義
/*
學(xué)過C語言的小伙伴們都知道有類型別名的概念,就是將已經(jīng)定義好的類型定義為我們自己所指定的自定義類型。
swift中,使用typealias關(guān)鍵字聲明。
//typealias <#type name#> = <#type expression#>
*/
do {
print("\n-----------1.類型定義----------------\n")
// 這里將MyInt定義為Int32類型
typealias MyInt = Int32
// 這里將MyArray定義為一個整型數(shù)組
typealias MyArray = [MyInt]
// 這里將VoidFuncType定義為 () -> Void 的函數(shù)類型
typealias VoidFuncType = () -> Void
// 這里將Tuple定義為(Int, Float, String)的元組
typealias Tuple = (Int, Float, String)
// 使用
// 這里的a的類型是MyInt ,實(shí)際上相當(dāng)于Int32類型
let a: MyInt = 100 + MyInt.min
print("a = \(a)")
let array: MyArray = [1, 2, 3]
print("array: \(array)")
let tuple: Tuple = (10, 1.5, "abc")
print("tuple: \(tuple.0)")
func foo() {
print("今天天氣不錯 ")
}
let ref: VoidFuncType
ref = foo
ref()
}
//2. 元類型
/*
什么是元類型?
元類型是指可引用某個類型的類型對象的類型。
有點(diǎn)兒像繞口令,不甚明白。
*/
protocol Prot {
/// 計(jì)算式屬性
static var s: Int { get }
/// 類型方法
static func method()
}
do {
print("\n----------2. 元類型------------\n")
struct MyStruct: Prot {
static var s: Int {
return 1
}
static func method() {
print("這是一個結(jié)構(gòu)體")
}
}
class MyClass: Prot {
static var s: Int {
return 100
}
static func method() {
print("這是一個類")
}
}
/*
這里使用MyStruct結(jié)構(gòu)體的元類型定義了一個類型對象st,其類型是MyStruct.Type,
而MyStruct.self 則是MyStruct這一類型的實(shí)體。
*/
let st: MyStruct.Type = MyStruct.self
/*
這里用MyClass類的元類型定義了一個類型對象ct,其類型是MyClass.Type, MyClass.self是
這一類型的實(shí)體。
*/
let ct: MyClass.Type = MyClass.self
/*
這里使用Prot的元類型定義了一個類型對象pt,然后指向了st的元類型實(shí)體。
*/
var pt: Prot.Type = st
print("pt: \(pt.s)")
pt.method()
pt = ct
print("pt: \(pt.s)")
pt.method()
/*
結(jié)果:
pt: 1
這是一個結(jié)構(gòu)體
pt: 100
這是一個類
*/
/*
小結(jié):
從這里可以看出,元類型能夠使用同一個對象指向不同類型的實(shí)體。
*/
}
/*
swift中,不僅類類型可以訪問self屬性,對象也是可以訪問self的,只不過得到的結(jié)果不是元類型實(shí)體
而是自身的值。
*/
do {
let a = 10.self
print("a = \(a)")
let tuple = (10, 12.3, "哈哈哈").self
print("tuple: \(tuple)")
}
//3. 類型獲取
/*
上面我們了解到元類型以及元類型實(shí)體。在傳遞的過程中,我們想知道目前對象指向的到底是什么類型呢?
這個時候我們就能使用 “類型獲取”來了解當(dāng)前的類型。
*/
print("\n--------------3. 類型獲取----------------\n")
protocol PA {
static var s: Int { get }
static func method()
init()
func foo()
}
do {
struct MyStruct: PA {
static var s: Int {
return 10
}
static func method() {
print("哈哈哈哈,結(jié)構(gòu)體啊")
}
func foo() {
print("結(jié)構(gòu)體中的方法")
}
}
class MyClass: PA {
static var s: Int {
return 100000
}
static func method() {
print("喲呼呼, 這是一個類")
}
func foo() {
print("這是一個類中的方法")
}
required init() {
print("這是一個類的初始化方法")
}
deinit {
print("類被銷毀了")
}
}
// 定義一個方法,參數(shù)是PA的元類型
func typeFetch(t: PA.Type) {
print("value: \(t.s)")
t.method()
let obj = t.init()
print("obj: \(obj)")
obj.foo()
}
let ms: PA = MyStruct()
let mc: PA = MyClass()
typeFetch(t: type(of: ms))
typeFetch(t: type(of: mc))
/*
結(jié)果:
這是一個類的初始化方法
value: 10
哈哈哈哈,結(jié)構(gòu)體啊
obj: MyStruct()
結(jié)構(gòu)體中的方法
value: 100000
喲呼呼, 這是一個類
這是一個類的初始化方法
obj: swift20_類型定義投射_.(unknown context at 0x1004e634c).MyClass
這是一個類中的方法
類被銷毀了
類被銷毀了
*/
}
// 4.Any與AnyObject
/*
本節(jié)中,我們談?wù)剆wift的根類型。大部分現(xiàn)在化的面向?qū)ο缶幊陶Z言都有自己的根類型。這些面向?qū)ο缶幊陶Z言中
的根類型的對象引用可以指向該編程語言中任意類類型的對象實(shí)例。
swift編程語言有兩個根類型,
一個是Any,它可以指向swift中的任一類型;
還有一個是AnyObject,它其實(shí)是一個協(xié)議類型,用于指向任一類類型的對象引用。
*/
do {
struct MyStruct {
}
class MyClass {
}
func foo() {
}
var obj: Any
obj = MyStruct()
obj = MyClass()
obj = foo
print("obj = \(obj)")
let cla: AnyObject = MyClass()
print("cla = \(cla)")
/*
不過,這兩種類型聲明的對象一般無法直接使用,需要類型投射才能進(jìn)行使用。
*/
}
// 5. 類型投射
/*
當(dāng)我們有根類型的對象,如何將這個對象轉(zhuǎn)為具體的類型呢?這個時候就需要類型投射了。
swift語言中,提供了兩種投射操作符,分別是 as! 和 as?
由于向下投射可能會失敗,所以一般情況下,我們使用as?進(jìn)行操作,它返回一個optional對象。
*/
do {
print("\n-----------5. 類型投射------------\n")
var obj: Any = 10
/*
這里編譯的時候回報(bào)錯:
Could not cast value of type 'Swift.Int' (0x1005720b0) to 'Swift.Double' (0x100571718).
為什么呢?因?yàn)閛bj是Int類型,不能直接投射成Double。
*/
//let value = obj as! Double
//print("value = \(value)")
let value2 = obj as! Int
print("value2 = \(value2)")
// 結(jié)果:value2 = 10
}
protocol PB {
func method()
}
do {
enum MyEnum: PB {
case one, two, three
func method() {
print("現(xiàn)在的值是 \(self)")
}
func foo() {
print("這是枚舉中的方法 foo")
}
}
struct MyStruct: PB {
func method() {
print("這是一個結(jié)構(gòu)體 method")
}
func foo() {
print("這是一個結(jié)構(gòu)體, foo")
}
}
class Father: PB {
func method() {
print("這是一個類,method")
}
func foo() {
print("這是類呢,哈哈哈哈哈")
}
}
class Child: Father {
override func method() {
print("這里是Child,method")
}
override func foo() {
print("這里是Child,foo ")
}
}
func test(ref: Any) {
if let obj = ref as? MyEnum {
obj.foo()
}
if let obj = ref as? MyStruct {
obj.foo()
}
if let obj = ref as? Father {
obj.foo()
}
if let obj = ref as? Child {
obj.foo()
}
if let obj = ref as? PB {
obj.method()
}
}
let ref: Any = test(ref: )
let fun = ref as! (Any) -> Void
fun(MyEnum.one)
fun(MyStruct())
fun(Father())
fun(Child())
/*
結(jié)果:
這是枚舉中的方法 foo
現(xiàn)在的值是 one
這是一個結(jié)構(gòu)體, foo
這是一個結(jié)構(gòu)體 method
這是類呢,哈哈哈哈哈
這是一個類,method
這里是Child,foo
這里是Child,foo
這里是Child,method
*/
}
// 6. 類型檢查
/*
我們了解了類型投射之后,有時候我們需要檢查某個對象類型的時候就可以使用as?進(jìn)行判斷。但是這不夠直接,
我們可以使用更加直觀的操作符 is。
*/
protocol PC {
}
do {
print("\n-----------6. 類型檢查------------\n")
class Father: PC {
}
class Child: Father {
}
var obj: Any = Father()
if obj is PC {
print("這是一個協(xié)議PC")
}
if obj is Father {
print("這是一個Father類")
}
obj = Child()
if obj is PC {
print("哈哈哈哈,pc")
}
if obj is Child {
print("這是一個Child")
}
if obj is Father {
print("哈哈哈哈,F(xiàn)ather")
print("\(type(of: obj))")
}
}
// 7. 嵌套類型
/*
與C++ 、Java等傳統(tǒng)的面向?qū)ο蟮木幊陶Z言一樣,swift也支持嵌套類型。
*/
do {
print("\n-------------7. 嵌套類型--------------\n")
struct Test {
private var member: Int = 1
enum MyEnum {
case one, two, three
class MyClass {
private var p = 0.5
func hello(test: Test) {
print("value = \(test.member)")
}
}
func test(cl: MyClass) {
print("哈哈哈哈哈,test \(self)")
}
}
func foo(cls: MyEnum.MyClass) {
cls.hello(test: self)
}
}
let t = Test()
let e = Test.MyEnum.two
let c = Test.MyEnum.MyClass()
t.foo(cls: c)
e.test(cl: c)
}