swift 包含三种类型(type): 结构体(structure),枚举类型(enumeration),类( class)
其中 结构体(structure)和枚举类型(enumeration)是值类型(value type ),类( class)是引用类型(reference type )
但是与OC不同的是, 结构体(structure)和枚举类型(enumeration)也可以拥有方法(method),其中方法可以为实例方法(instance method),也可以为类方法(type method),实例方法是和类型的一个实例绑定的。
示例一:
struct Point { var x = 0,y = 0 func moveByPoint(x:Int,yBy y:Int) { self.x += x // Cannot invoke '+=' with an argument list of type '(Int,Int)' self.y += y // Cannot invoke '+=' with an argument list of type '(Int,Int)' } }
编译器抛出错误,提示说明不能在实例方法中修改结构体内的属性值。
为了能够在实例方法中修改属性值,可以在方法定义前添加关键字 mutating
如下所示:
struct Point { var x = 0,y = 0 mutating func moveByPoint(x:Int,yBy y:Int) { self.x += x self.y += y } } var p = Point(x: 5,y: 5) p.moveXBy(3,yBy: 3)
另外,在添加关键字 mutating的枚举类型实例方法中,也可以直接修改self属性值。如下所示:
enum BlackOrWhite { case Black,White mutating func switch() { switch self { case Black: self = White case White: self = Black } } } var blackOrWhite = BlackOrWhite.Black <pre name="code" class="plain">blackOrWhite.switch()
blackOrWhite.switch()
BlackOrWhite枚举类型定义了Black和White两种状态,在switch实例方法中动态改变self属性的值。
当然,在类( class)类型中的方法默认情况下就可以修改属性值,不存在以上问题。
示例二Swift 的协议(protocol) 不仅可以被类( class)类型实现,也适用于结构体(structure)和枚举类型( enumeration)。因此,我们在写给别人用的接口时需要多考虑是否使用mutating 来修饰方法。
比如,有一个交通工具协议Vehicle,然后我们有一个结构体MyCar实现这个协议。如下所示:
protocol Vehicle { var numberOfWheels: Int {get} var color: UIColor {get set} mutating func changeColor() } struct MyCar: Vehicle { let numberOfWheels = 4 var color = UIColor.blueColor() mutating func changeColor() { color = UIColor.redColor() } }
问题一:如果把protocol 定义中的mutating 去掉的话,编译器抛出错误,提示没有实现接口。
问题二:如果去掉结构体中的mutating 的话,就与示例一结构体的第一种方式相同的,编译器抛出错误,提示不能改变结构体内的属性值。