方法是与某些特定类型相关联的函数。类、结构体、枚举都可以定义实例方法;实例方法为给定类型的实例封装了具体的任务与功能。类、结构体、枚举也可以定义类型方法;类型方法与类型本身相关联。类型方法与 Objective-C 中的类方法(class methods)相似。
结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一。在 Objective-C 中,类是唯一能定义方法的类型。
但在 Swift 中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活地在你创建的类型(类/结构体/枚举)上定义方法。
实例方法 (Instance Methods)
实例方法是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能,并以此来支撑实例的功能。
实例方法要写在它所属的类型的前后大括号之间。实例方法能够隐式访问它所属类型的所有的其他实例方法和属性。实例方法只能被它所属的类的某个特定实例调用。实例方法不能脱离于现存的实例而被调用。
下面的例子,定义一个很简单的Counter
类,Counter
能被用来对一个动作发生的次数进行计数:
Count类定义了三个实例方法
class Counter {
var count = 0
func increment() {
count += 1
print(count)
}
func increment(by amount: Int) {
count += amount
print(count)
}
func reset() {
count = 0
print(count)
}
}
调用方法
let numCount = Counter()
numCount.increment()
numCount.increment(by: 5)
numCount.reset()
// 1
// 6
// 0
self 属性
类型的每一个实例都有一个隐含属性叫做self
,self
完全等同于该实例本身。你可以在一个实例的实例方法中使用这个隐含的self
属性来引用当前实例。
实际上,你不必在你的代码里面经常写self
。不论何时,只要在一个方法中使用一个已知的属性或者方法名称,如果你没有明确地写self
,Swift 假定你是指当前实例的属性或者方法。这种假定在上面的Counter
中已经示范了:Counter
中的三个实例方法中都使用的是count
(而不是self.count
)。
使用这条规则的主要场景是实例方法的某个参数名称与实例的某个属性名称相同的时候。在这种情况下,参数名称享有优先权,并且在引用属性时必须使用一种更严格的方式。这时你可以使用self
属性来区分参数名称和属性名称。
self
消除方法参数
x
和实例属性
x
之间的歧义
self
前缀,Swift 就认为两次使用的x
都指的是名称为x
的函数参数。struct Point {
var x = 0.0, y = 0.0
func isToTheRightOfX(x: Double) -> Bool {
print("This point is to the right of the line where x == \(x)")
return self.x > x
}
}
let somePoint = Point(x: 4.0, y: 5.0)
somePoint.isToTheRightOfX(x: 1.0)
输出This point is to the right of the line where x == 1.0
在实例方法中修改值类型
结构体和枚举是值类型。默认情况下,值类型的属性不能在它的实例方法中被修改。
但是,如果你确实需要在某个特定的方法中修改结构体或者枚举的属性,你可以为这个方法选择可变(mutating)
行为,然后就可以从其方法内部改变它的属性;并且这个方法做的任何改变都会在方法执行结束时写回到原始结构中。方法还可以给它隐含的self
属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例。
要使用可变
方法,将关键字mutating
放到方法的func
关键字之前就可以了:
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOfX(x: Double) -> Bool {
print("This point is to the right of the line where x == \(x)")
return self.x > x
}
mutating func moveByx(deltaX: Double,deltaY: Double){
x += deltaX
y += deltaY
print("This point is x: \(x) y: \(y)")
}
}
var somePoint = Point(x: 4.0, y: 5.0)
somePoint.moveByx(deltaX: 6.0, deltaY: 6.0)
输出This point is x: 10.0 y: 11.0
在可变方法中给 self 赋值
可变方法能够赋给隐含属性self
一个全新的实例。上面Point
的例子可以用下面的方式改写:
mutating func moveByx(deltaX: Double,deltaY: Double){
// x += deltaX
// y += deltaY
self = Point(x: x + deltaX,y: y + deltaY)
print("This point is x: \(x) y: \(y)")
}
枚举的可变方法可以把self
设置为同一枚举类型中不同的成员
enum ChangeSwitch{
case off, Low, High
mutating func next(){
switch self {
case .off:
self = .Low
case .Low:
self = .High
case .High:
self = .off
}
print(self)
}
}
var changeEnum = ChangeSwitch.Low
changeEnum.next()//High
类型方法
实例方法是被某个类型的实例调用的方法。你也可以定义在类型本身上调用的方法,这种方法就叫做类型方法。在方法的func
关键字之前加上关键字static
,来指定类型方法。类还可以用关键字class
来允许子类重写父类的方法实现。
注意
在 Objective-C 中,你只能为 Objective-C 的类类型(classes)定义类型方法(type-level methods)。在 Swift 中,你可以为所有的类、结构体和枚举定义类型方法。每一个类型方法都被它所支持的类型显式包含。
类型方法和实例方法一样用点语法调用。但是,你是在类型上调用这个方法,而不是在实例上调用。
class SomeClass {
class func someTypeMethod() {
// 在这里实现类型方法
}
}
SomeClass.someTypeMethod()