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的不同含义,正确使用
相关推荐
sakiko_7 小时前
UIKit学习笔记4-使用UITableView制作滚动视图
笔记·学习·ios·swift·uikit
小锋学长生活大爆炸10 小时前
【开源软件】这次iPhone也是用上Claw了 | PhoneClaw
ios·开源软件·iphone·claw
SameX14 小时前
独立开发一个把走过的路变成 km² 的 App,聊聊 25m 网格和后台 GPS 的坑
ios
XD74297163615 小时前
科技早报晚报|2026年4月30日:Agent 安全壳、浏览器 iOS 测试台与可穿戴数据 API,今天更值得看的 3 个技术机会
科技·ios·开源项目·科技新闻·开发者工具
北京自在科技18 小时前
Find Hub App 小更新
android·ios·安卓·findmy·airtag
2501_9159214318 小时前
HTTPS前端劫持 新一代流量劫持解决方案
前端·网络协议·ios·小程序·https·uni-app·iphone
911hzh19 小时前
Flutter WebRTC iOS 原理解析:从 getUserMedia 到 Texture,讲清视频采集、纹理渲染与远端通话链路
flutter·ios·webrtc
软泡芙19 小时前
【iOS】 开发入门指南
ios
水中加点糖20 小时前
ios中使用DockKit和CoreML实现自定义目标的自动跟随(一)
目标检测·ios·目标跟踪·硬件控制·dockkit
2501_9159090620 小时前
iOS应用签名的三种方法全解析:从官方到第三方工具
android·ios·小程序·https·uni-app·iphone·webview