方法
目录
实例方法
实例方法(Instance Method)是属于特定类、结构体或枚举的实例的方法。
基本语法
swift
struct Counter {
var count = 0
// 实例方法
func increment() {
count += 1
}
func increment(by amount: Int) {
count += amount
}
func reset() {
count = 0
}
}
var counter = Counter()
counter.increment()
counter.increment(by: 5)
counter.reset()
实例方法的特点
- 实例方法只能被类型的实例调用
- 实例方法可以访问实例的属性和其他实例方法
- 实例方法在调用时会自动获得该实例的引用
self的使用
self
属性是每个实例隐式拥有的属性,完全等同于该实例本身。
基本用法
swift
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOf(x: Double) -> Bool {
return self.x > x // 区分参数x和属性x
}
}
let point = Point(x: 4.0, y: 5.0)
print(point.isToTheRightOf(x: 1.0)) // true
何时使用self
通常情况下,不需要显式地写出self
,Swift会自动推断。但在以下情况下需要使用:
- 参数名与属性名相同时
- 闭包中访问实例属性时
- 方法返回self时
swift
struct Calculator {
var result: Double = 0
func add(_ value: Double) -> Calculator {
result += value
return self // 返回自身,支持链式调用
}
func multiply(_ value: Double) -> Calculator {
result *= value
return self
}
}
let calculator = Calculator()
let result = calculator.add(5).multiply(2).result // 10
mutating方法
值类型(结构体、枚举)的实例方法默认不能修改实例的属性。如果需要修改,必须使用mutating
关键字。
基本语法
swift
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var point = Point(x: 1.0, y: 1.0)
point.moveBy(x: 2.0, y: 3.0)
print(point) // Point(x: 3.0, y: 4.0)
mutating方法的特点
- 只有值类型(结构体、枚举)需要
mutating
关键字 - 类的实例方法不需要
mutating
关键字 mutating
方法可以为self
赋予一个全新的实例
swift
struct Point {
var x = 0.0, y = 0.0
mutating func moveToOrigin() {
self = Point(x: 0.0, y: 0.0)
}
}
枚举中的mutating方法
swift
enum TriStateSwitch {
case off, low, high
mutating func next() {
switch self {
case .off:
self = .low
case .low:
self = .high
case .high:
self = .off
}
}
}
var lightSwitch = TriStateSwitch.low
lightSwitch.next() // .high
lightSwitch.next() // .off
@discardableResult
@discardableResult
特性用于标记那些有返回值但调用者可以忽略返回值的方法。
基本用法
swift
struct Stack<T> {
var items: [T] = []
mutating func push(_ item: T) {
items.append(item)
}
@discardableResult
mutating func pop() -> T? {
return items.popLast()
}
}
var stack = Stack<Int>()
stack.push(1)
stack.push(2)
// 不使用@discardableResult会产生警告
let popped = stack.pop() // 使用返回值
stack.pop() // 忽略返回值,不会产生警告
什么时候使用@discardableResult
- 方法既可以用于获取值,也可以用于执行操作
- 调用者有时关心返回值,有时不关心
- 避免编译器产生"未使用的返回值"警告
swift
class Logger {
@discardableResult
func log(_ message: String) -> String {
let timestamp = Date().description
let logEntry = "[\(timestamp)] \(message)"
print(logEntry)
return logEntry
}
}
let logger = Logger()
logger.log("Error occurred") // 忽略返回值
let entry = logger.log("Info log") // 使用返回值
类型方法
类型方法(Type Method)是属于类型本身的方法,而不是属于类型的某个实例。
基本语法
swift
struct MathUtils {
// 类型方法
static func abs(_ number: Int) -> Int {
return number < 0 ? -number : number
}
static func max(_ a: Int, _ b: Int) -> Int {
return a > b ? a : b
}
}
// 调用类型方法
let result1 = MathUtils.abs(-10) // 10
let result2 = MathUtils.max(5, 8) // 8
static vs class
static
:不能被子类重写class
:可以被子类重写(仅限于类)
swift
class Vehicle {
static func staticMethod() {
print("Vehicle static method")
}
class func classMethod() {
print("Vehicle class method")
}
}
class Car: Vehicle {
// 不能重写static方法
// override static func staticMethod() { } // 编译错误
// 可以重写class方法
override class func classMethod() {
print("Car class method")
}
}
Vehicle.staticMethod() // Vehicle static method
Car.staticMethod() // Vehicle static method
Vehicle.classMethod() // Vehicle class method
Car.classMethod() // Car class method
类型方法的实际应用
swift
struct Temperature {
var celsius: Double
init(celsius: Double) {
self.celsius = celsius
}
// 类型方法:工厂方法
static func fromFahrenheit(_ fahrenheit: Double) -> Temperature {
return Temperature(celsius: (fahrenheit - 32) * 5/9)
}
static func fromKelvin(_ kelvin: Double) -> Temperature {
return Temperature(celsius: kelvin - 273.15)
}
}
let temp1 = Temperature(celsius: 25.0)
let temp2 = Temperature.fromFahrenheit(77.0)
let temp3 = Temperature.fromKelvin(298.15)
类型方法中的self
在类型方法中,self
指向类型本身:
swift
struct Counter {
static var count = 0
static func increment() {
self.count += 1 // self指向Counter类型
}
static func reset() {
count = 0 // 可以省略self
}
}
Counter.increment()
print(Counter.count) // 1
Counter.reset()
print(Counter.count) // 0
总结
方法类型对比
方法类型 | 调用方式 | 访问范围 | 修改实例 | 适用类型 |
---|---|---|---|---|
实例方法 | 实例.方法() | 实例属性和方法 | 需要mutating | 类、结构体、枚举 |
类型方法 | 类型.方法() | 类型属性和方法 | 不涉及实例 | 类、结构体、枚举 |
关键字总结
mutating
:值类型的实例方法修改属性时必须使用@discardableResult
:标记可忽略返回值的方法static
:定义不可重写的类型方法class
:定义可重写的类型方法(仅限类)self
:当前实例(实例方法)或类型(类型方法)的引用
最佳实践
- 实例方法:用于操作实例数据,提供实例相关的功能
- 类型方法:用于工厂方法、工具方法、类型相关的操作
- mutating方法:值类型需要修改自身时使用
- @discardableResult:既可以用于获取值也可以用于执行操作的方法
- 链式调用:方法返回self,支持链式编程风格
使用建议
- 优先使用实例方法处理实例相关的逻辑
- 使用类型方法提供工厂方法或工具函数
- 值类型修改自身时记得使用mutating
- 合理使用@discardableResult避免编译器警告
- 理解self的不同含义,正确使用