• 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"
  • 相关阅读:
    ubuntu安装Elasticsearch
    PHP如何计算脚本执行时间
    MVC+EF中返回JSON的性能和安全问题
    博客园最新的一个模板样式有问题
    Entity Framework 批量插入很慢吗?我自己测试下
    用 Raphaël 绘制中国地图 + 显示数据
    博客园的手机版(非官方) MVC+jQuery.Mobile
    BitCovert,与移位,加法性能比较
    探讨微软ASP.NET AJAX控件开发技术(客户端)
    (十三)树【C++刷题】
  • 原文地址:https://www.cnblogs.com/keqipu/p/7625807.html
Copyright © 2020-2023  润新知