zoukankan      html  css  js  c++  java
  • Swift教程之方法

    方法

    方法是与特定类型相关联的函数。类、结构体和枚举都可以定义实例方法,这些方法封装了特定任务和功能来处理给定类型的实例,也可以定义与类型本身相关联的类型方法(类似于Objective-C中的类方法)。


    ## 实例方法 实例方法是属于特定类、结构体或枚举的实例的函数。通过提供访问和修改实例属性的方法,或通过提供与实例的目的相关的功能来支持这些实例的函数,实例方法与函数具有完全相同的语法。

    实例方法具有对该类型的所有其他实例方法和属性的隐式访问,且只能在其所属类型的特定实例上调用实例方法,若没有现有的实例,则不能被单独调用。

    class Counter {
        var count = 0
        func increment() {
            count += 1
        }
        func increment(by amount: Int) {
            count += amount
        }
        func reset() {
            count = 0
        }
    }
    
    let counter = Counter()
    // the initial counter value is 0
    counter.increment()
    // the counter's value is now 1
    counter.increment(by: 5)
    // the counter's value is now 6
    counter.reset()
    // the counter's value is now 0
    

    self属性

    类型的实例都有一个self的隐式属性,它与实例本身完全相同。

    上述increment()方法修改如下:

    func increment() {
        self.count += 1
    }
    

    在代码中不需要显示书写self,Swift会假定在使用当前属性或方法名称时指向当前实例的属性或方法。

    当实例方法的参数名与该实例的属性名相同时,有必要使用self属性来区分参数名和属性名。

    struct Point {
        var x = 0.0, y = 0.0
        func isToTheRightOf(x: Double) -> Bool {
            return self.x > x
        }
    }
    let somePoint = Point(x: 4.0, y: 5.0)
    if somePoint.isToTheRightOf(x: 1.0) {
        print("This point is to the right of the line where x == 1.0")
    }
    // Prints "This point is to the right of the line where x == 1.0"
    

    若没有书写self前缀,Swift会假设两个x都是x的方法参数。

    在实例方法中修改值类型

    由于结构体和枚举是值类型,默认情况下,不能从其实例方法修改值类型的属性。

    使用mutating修饰符可以修改特定方法的结构体或枚举的属性,mutating关键字放在func关键字之前:

    struct Point {
        var x = 0.0, y = 0.0
        mutating func moveBy(x deltaX: Double, y deltaY: Double) {
            x += deltaX
            y += deltaY
        }
    }
    var somePoint = Point(x: 1.0, y: 1.0)
    somePoint.moveBy(x: 2.0, y: 3.0)
    print("The point is now at ((somePoint.x), (somePoint.y))")
    // Prints "The point is now at (3.0, 4.0)"
    

    不能在结构体类型常量上调用mutating方法,因为其属性不能更改。

    let fixedPoint = Point(x: 3.0, y: 3.0)
    fixedPoint.moveBy(x: 2.0, y: 3.0)
    // this will report an error
    

    在mutating方法中分配self

    mutating方法可以为隐式self属性分配一个全新的实例。

    struct Point {
        var x = 0.0, y = 0.0
        mutating func moveBy(x deltaX: Double, y deltaY: Double) {
            self = Point(x: x + deltaX, y: y + deltaY)
        }
    }
    

    枚举的mutating方法可以将隐式self属性设置为与同一枚举不同的情况:

    enum TriStateSwitch {
        case off, low, high
        mutating func next() {
            switch self {
            case .off:
                self = .low
            case .low:
                self = .high
            case .high:
                self = .off
            }
        }
    }
    var ovenLight = TriStateSwitch.low
    ovenLight.next()
    // ovenLight is now equal to .high
    ovenLight.next()
    // ovenLight is now equal to .off
    

    ## 类型方法 类型方法是定义在类型本身上调用的方法。通过在方法的**func**关键字前编写**static**关键字来指示类型方法,也可以使用**class**关键字允许子类重写超类的该方法的实现。

    在类型上使用点语法调用类型方法,而不是该类型的实例:

    class SomeClass {
        class func someTypeMethod() {
            // type method implementation goes here
        }
    }
    SomeClass.someTypeMethod()
    

    在类型方法体内,隐式self属性指类型本身,而不是该类型的实例,可以使用self来消除类型属性和类型方法参数之间的歧义。

    struct LevelTracker {
        static var highestUnlockedLevel = 1
        var currentLevel = 1
        
        static func unlock(_ level: Int) {
            if level > highestUnlockedLevel { 
            highestUnlockedLevel = level 
            }
        }
        
        static func isUnlocked(_ level: Int) -> Bool {
            return level <= highestUnlockedLevel
        }
        
        @discardableResult
        mutating func advance(to level: Int) -> Bool {
            if LevelTracker.isUnlocked(level) {
                currentLevel = level
                return true
            } else {
                return false
            }
        }
    }
    
    class Player {
        var tracker = LevelTracker()
        let playerName: String
        func complete(level: Int) {
            LevelTracker.unlock(level + 1)
            tracker.advance(to: level + 1)
        }
        init(name: String) {
            playerName = name
        }
    }
    
    var player = Player(name: "Argyrios")
    player.complete(level: 1)
    print("highest unlocked level is now (LevelTracker.highestUnlockedLevel)")
    // Prints "highest unlocked level is now 2"
    
    player = Player(name: "Beto")
    if player.tracker.advance(to: 6) {
        print("player is now on level 6")
    } else {
        print("level 6 has not yet been unlocked")
    }
    // Prints "level 6 has not yet been unlocked"
  • 相关阅读:
    gain 基尼系数
    luogu P5826 【模板】子序列自动机 主席树 vector 二分
    牛客挑战赛39 树与异或 离线 树上莫队 树状数组 约数
    4.22 省选模拟赛 三元组 manacher 回文自动机
    4.22 省选模拟赛 最优价值 网络流 最大权闭合子图
    4.18 省选模拟赛 消息传递 树剖 倍增 线段树维护等比数列
    luogu P4008 [NOI2003]文本编辑器 splay 块状链表
    牛客挑战赛39 密码系统 后缀数组
    luogu P1526 [NOI2003]智破连环阵 搜索+最大匹配+剪枝
    luogu P4095 [HEOI2013]Eden 的新背包问题 多重背包 背包的合并
  • 原文地址:https://www.cnblogs.com/keqipu/p/7625807.html
Copyright © 2011-2022 走看看