Swift语言学习笔记(六)

来源:互联网 发布:js ajax多线程 编辑:程序博客网 时间:2024/06/04 20:13


97. 可选链(optional chaining)的例子:


class A {


    var m : Int = 10


}


class B {


    var a : A?


}


class C {


    var b : B?


}


var c = C()


var k = c.b?.a?.m


println(k)


上面的例子中,我们在为变量k赋值的时候,使用的是c.b?.a?.m,这里并没有使用c.b!.a!.m,否则由于b或者a是空,会抛出运行时的异常。而使用“?”,会导致返回一个Int?给k,尽管属性“m”的类型是Int,并不是Int?,可选链避免由于元素为nil导致异常的发生。


甚至还可以使用可选链来检测方法是否执行成功,甚至是无返回值的方法(无返回值的方法实际返回的是Void?),如果函数的返回值是nil,则表明函数执行失败,否则表示函数成功执行。


对于下标(subscript)使用可选链,问号要位于下标的中括号前面,例如:


var v = someClassInstance1.subClassInstance1?[0].prop


对于函数使用可选链,问号位于函数圆括号的后面:


var v = someClassInstance1.fun1()?.prop


98. Swift中使用isas来进行类型转换的判断以及转换。其中as运算符会强制转换为目标类型,如果转换失败会抛异常,所以,如果在不确定转换是否成功的情况下,使用as?运算符,转换失败会返回nil


99. Swift中的变量绑定会自动将可选类型变量的值解出来,例如:


var i : Int? = 10


var t = (i, 0)


switch t {


case (let m, 0):


    println(m)


default:


    break


}


例子中常量m直接得到的就是可选类型变量i存储的Int值。


100.          Swift中提供AnyObjectAny两种特殊类型,AnyObject可以用来指向任何类的实例,Any可以指向任何类型的实例,除了函数类型。例如:


var a : AnyObject = SomeClass()


var a : Any = 10


101.          Swift中可以使用as将数组类型批量做类型转换,例如:


class A {


}


var someObjects : AnyObject[] = [A(), A(), A()]


var arr = someObjects as A[]


102.          Swift中允许使用类型嵌套,类型嵌套直接在一个类型定义中嵌套另一个即可:


class A{


    class B {


        enum C {


           case C1, C2, C3


        }


    }


}


要使用嵌套类型,用类名引用:


var c = A.B.C.C1


103.          Swift中通过扩展(extension)来为已知类、结构体或者枚举类型添加功能,类似于Object-C中的categorySwift中的扩展可以添加的内容:


计算属性(get、set方法)和静态计算属性


类方法和实例方法


初始化方法


下标(subscript)


嵌套类型


协议继承关系


104.          Swift中扩展使用extension关键字来定义:


extension SomeType {


}


extension SomeType : SomeProtocol {


}


105.          Swift中扩展可以添加初始化方法,但是不能添加指派初始化方法,也不能添加析构方法。


106.          在定义类的时候,如果类既有基类,又实现了某些协议(protocol),那么在声明的时候,一定要把基类写在最前面:


class ClassName : BaseClassName, ProtocolName1, Protocol2… {


}


107.          Swift中的协议(protocol)可以定义继承类必须实现的属性,属性可以使只读的,也可以是读写的(注意,协议中定义的属性都是用var关键字,静态属性和方法都使用关键字class):


protocol DemoProtocol {


var prop1 : Int { get set }


var prop2 : String { get }


}


虽然在定义的时候使用get/set来指明属性的读写性质,但是实现类中并没有要求一定要定义属性的get和set方法,只要实现类中存在名称相同类型一致的属性即可。要注意的一点限制是:如果协议中定义的属性为读写属性,则实现类中对应属性不能为常量或者只读属性。


108.          Swift协议中定义的方法不能指定参数默认值。


109.          Swift中协议可以继承其他协议(C#中也可以),语法和类定义类似。


110.          如果需要“一个”类型同时继承多个协议时,可以使用protocol<Protocol1,Protocol2, …>来将多个协议组装成一个整体,例如:


protocol P1 {


}


protocol P2 {


}


protocol P3 {


}


class C1 : P1, P2, P3 {


}


func demoFunc(demoClass : protocol<P1, P2, P3>) {


}


var c = C1()


demoFunc(c)


这种组装只能是临时的一个类型,不能作为一种新的协议类型来定义变量等。


111.          对于协议类型,也可以使用isasas?来进行类型判断和类型转换,但是如果想要使用is关键字来判断类型,必须要在protocol关键字前面添加@objc关键字来进行修饰,且使用@objc来修饰的协议不能被结构体和枚举类型继承,asas?关键字不需要这个要求。例如:


@objc protocol DemoProtocol { }


class A : DemoProtocol { }


class B { }


struct B : DemoProtocol {}             //这行编译不过去


var a : AnyObject = A()


var b : AnyObject = B()


var c : Bool = a is DemoProtocol


var d = b as?DemoProtocol           //d =nil


注意我们定义变量a的时候特意定义a的类型为AnyObject,如果不这样做,会提示我们“a isDemoProtocol”这句有错误,因为如果a不定义成AnyObject,编译器会推测出a的类型为A,继承DemoProtocol协议,因此a isDemoProtocol这句永远为真,所以会报错来提示我们去掉不必要的语法。


112.          使用@objc关键字定义的协议中可以定义可选(optional)的方法和属性,通过在方法和属性的声明最前面添@optional关键字来实现。例如:


@objc protocol DemoProtocol {


@optional func demoFunc()


@optional var demoProp


}


对于可选的方法和属性,继承类可以选择实现或者不实现。因此,在调用时为了保证程序能正常运行,不会因为方法或者属性没有实现而抛异常,在调用的时候在方法名或者属性后面添加?(和可选链的用法相同)来保证返回可选类型。


113.          Swift中的泛型方法定义:


func genericFuncDemo<T>(para1 : T, para2 : T …) {


}


调用的时候很简单,不需要显式地指明T的类型:


var p1 = “abc”


var p2 = “def”


genericFuncDemo(para1 : p1, para2 : p2 …)


可以定义多个占位类型:


func demoFunc<T, U, P>(para1 : T, para2 : U, para3 : P…) {


}


114.          Swift中的泛型类、泛型结构体和泛型枚举类型的定义都是在类名和结构体名后面加上<>,里面填写泛型的占位类型,例如上面的TUP这些。占位类型的命名最好用大写开头,以表明它是一个类型而非一个值。


115.          可以在定义泛型的时候使用类型约束,例如:


func someFunc<T : SomeClass, U : SomeProtocol>(a : T, b: U) {


}


例如可以定义T继承Equatable,U继承Comparable。


116.          Swift中可以为协议定义关联类型,使用typealias关键字来定义关联类型,一个协议中可以定义多个关联类型,例如:


protocol Container {


typealias ItemType


mutating func append(item : ItemType)


var count : Int { get }


subscript(i : Int) -> ItemType { get }


}


上面的关联类型保证了Container中的append方法添加的元素和下标取出的元素类型一致。


下面的结构体实现Container协议中定义的方法,通过typealias ItemType =Int来指定具体的关联类型是Int型:


struct IntStack : Container {


var items = Int[]()


typealias ItemType = Int


mutating func append(item : Int) {


    items.append(item)


}


var count : Int {


    return items.count


}


subscript(i : Int) -> Int {


    return items[i]


}


}


实际上,即使不写typealias ItemType =Int这条语句,Swift也能够推测出ItemType是Int型,编译也能够正常通过,这是因为IntStack中实现了所有Container中定义的方法。


也可以结合泛型和关联类型,例如将上面的IntStack改成泛型结构体。


117.          除了泛型约束之外,还可以使用where子句来对泛型加以约束,例如:


func isAllItemsMatch<C1 : Container, C2 : Container whereC1.ItemType = C2.ItemType, C1.ItemType : Equatable>(someContainer : C1,anotherContainer : C2) -> Bool {


    //compare every element in the twocontainers


}


where子句中可以使用andor来进行逻辑连接。



82 0
原创粉丝点击