9.方法

方法

目录

  1. 实例方法
  2. self的使用
  3. mutating方法
  4. @discardableResult
  5. 类型方法

实例方法

实例方法(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会自动推断。但在以下情况下需要使用:

  1. 参数名与属性名相同时
  2. 闭包中访问实例属性时
  3. 方法返回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:当前实例(实例方法)或类型(类型方法)的引用

最佳实践

  1. 实例方法:用于操作实例数据,提供实例相关的功能
  2. 类型方法:用于工厂方法、工具方法、类型相关的操作
  3. mutating方法:值类型需要修改自身时使用
  4. @discardableResult:既可以用于获取值也可以用于执行操作的方法
  5. 链式调用:方法返回self,支持链式编程风格

使用建议

  • 优先使用实例方法处理实例相关的逻辑
  • 使用类型方法提供工厂方法或工具函数
  • 值类型修改自身时记得使用mutating
  • 合理使用@discardableResult避免编译器警告
  • 理解self的不同含义,正确使用
相关推荐
形影相吊1 小时前
iOS防截屏实战
ios
吴Wu涛涛涛涛涛Tao1 小时前
Flutter 弹窗解析:从系统 Dialog 到完全自定义
flutter·ios
kymjs张涛3 小时前
零一开源|前沿技术周报 #7
android·前端·ios
思考着亮5 小时前
15-错误处理
ios
思考着亮6 小时前
6.结构体和类
ios
思考着亮6 小时前
7.闭包
ios
咕噜签名分发冰淇淋8 小时前
申请注册苹果iOS企业级开发者证书需要公司拥有什么规模条件
macos·ios·cocoa
2501_9159184118 小时前
Fiddler中文版全面评测:功能亮点、使用场景与中文网资源整合指南
android·ios·小程序·https·uni-app·iphone·webview
不知名It水手20 小时前
uniapp运行项目到ios基座
ios·uni-app·cocoa