在swift当中, 除了类可以定义方法, 结构体和枚举也可以定义方法, 这是Swift 与 C/Objective-C 的主要区别之一.
class Counter {
//保持对当前计数器值的追踪。
var count = 0
//increment让计数器按一递增
func increment() {
count += 1 //注意. 此处不能使用count++, 在swift3.x里面, 已经废除++, --的写法
}
//incrementBy(amount: Int)让计数器按一个指定的整数值递增;
func incrementBy(amount: Int) {
count += amount
}
//reset将计数器重置为0。
func reset() {
count = 0
}
}
方法的使用, 与OC一样, 使用, 点语法访问
let counter = Counter()
// 初始计数值是0
counter.increment()
// 计数值现在是1
counter.incrementBy(amount: 5) //swift3.x写法
//counter.incrementBy(5) , swift2.x写法
// 计数值现在是6
counter.reset()
// 计数值现在是0
self属性
类型的每一个实例都有一个隐含属性叫做self,self完全等同于该实例本身。你可以在一个实例的实例方法中使用这个隐含的self属性来引用当前实例。
上面例子中的increment方法还可以这样写:
func increment() {
self.count++
}
实际上,你不必在你的代码里面经常写self。不论何时,只要在一个方法中使用一个已知的属性或者方法名称,如果你没有明确的写self,Swift 假定你是指当前实例的属性或者方法。这种假定在上面的Counter中已经示范了:Counter中的三个实例方法中都使用的是count(而不是self.count)。
使用这条规则的主要场景是实例方法的某个参数名称与实例的某个属性名称相同的时候。在这种情况下,参数名称享有优先权,并且在引用属性时必须使用一种更严格的方式。这时你可以使用self属性来区分参数名称和属性名称。
在实例方法中修改值类型
mutating方法(变异方法)
结构体和枚举是值类型。一般情况下,值类型的属性不能在它的实例方法中被修改。
如果你确实需要在某个具体的方法中修改结构体或者枚举的属性,你可以选择变异(mutating)这个方法,然后方法就可以从方法内部改变它的属性;并且它做的任何改变在方法结束时还会保留在原始结构中。方法还可以给它隐含的self属性赋值一个全新的实例,这个新实例在方法结束后将替换原来的实例。
struct Point {
var x = 0.0, y = 0.0
//使用mutating关键字进行声明, 来修改结构体和枚举的属性值
mutating func moveByX(deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(deltaX: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
//不能用声明为常量(let)类型的结构体调用变异方法,因为常量的属性不能被改变,即使想改变的是常量的变量属性也不行
let fixedPoint = Point(x: 3.0, y: 3.0) //✅正确写法, 把fixedPoint结构体声明为var
fixedPoint.moveByX(deltaX: 2.0, y: 3.0) //error -> change 'let' to 'var' to make it mutable
在变异方法中给self赋值(Assigning to self Within a Mutating Method)
上面的例子可以改写成
struct Point {
var x = 0.0, y = 0.0
mutating func moveByX(deltaX: Double, y deltaY: Double) {
self = Point(x: x + deltaX, y: y + deltaY) //创建一个新的结构体, 并把它赋值给自己
}
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(deltaX: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
枚举的变异方法
//枚举的变异方法可以把self设置为相同的枚举类型中不同的成员:
enum TriStateSwitch {
case Off, Low, High
mutating func next() {
switch self {
case .Off: // case时别忘记使用(.)运算符, 否则 error: enum element 'Off' cannot be referenced as an instance member
self = .Low
case .Low:
self = .High
case .High:
self = .Off
}
}
}
var ovenLight = TriStateSwitch.Low
ovenLight.next()
// ovenLight 现在等于 .High
ovenLight.next()
// ovenLight 现在等于 .Off
类型方法(Type Methods)
实例方法是被类型的某个实例调用的方法。你也可以定义类型本身调用的方法,这种方法就叫做类型方法。声明类的类型方法,在方法的func关键字之前加上关键字class;声明结构体和枚举的类型方法,在方法的func关键字之前加上关键字static。
//类型方法和实例方法一样用点语法调用。但是,你是在类型层面上调用这个方法,而不是在实例层面上调用
class SomeClass {
class func someTypeMethod() {
// type method implementation goes here
//在类型方法的方法体(body)中,self指向这个类型本身,而不是类型的某个实例。对于结构体和枚举来说,这意味着你可以用self来消除静态属性和静态方法参数之间的歧义(类似于我们在前面处理实例属性和实例方法参数时做的那样)。
}
}
SomeClass.someTypeMethod()
//一般来说,任何未限定的方法和属性名称,将会来自于本类中另外的类型级别的方法和属性。一个类型方法可以调用本类中另一个类型方法的名称,而无需在方法名称前面加上类型名称的前缀。同样,结构体和枚举的类型方法也能够直接通过静态属性的名称访问静态属性,而不需要类型名称前缀。