第十一章 方法

2. Type Method (类型方法)

方法中的实例方法已经在上个章节中表述过了,实例方法是一个调用某个特定类型的实例里面的一种方法,也可以定义一个调用在类型本身的方法(you can also define methods that are called on the type itself),这种调用形式的方法我们称之为类型方法(Type Method)。

static关键字在结构体里介绍并引出这个类型方法,不同的是在类里面要用到Class关键字介绍引出该类型方法。从而允许子类重写父类方法的实现。

像实例方法那样可以用dot语法来调用类型方法。然而不同的是:调用类型方法的是调用在类型上的 不是调用在类型的实例上的。下面是如何在SomeClass类上调用类型方法的例子:

class SomeClass {
    class func someTypeMethod() {
    /* 这里有一个隐含的self属性
       该隐含的self属性指代的是类型本身,而不是类型的某个实例
       也就是说可以用self来区分类型属性和类型方法参数 */
    }
}
// 用dot语法来调用类的类型方法
SomeClass.someTypeMethod()

下面这个例子定义了LevelTracker的结构体,用来追踪玩家在游戏不同阶段的进度。虽然这是一个单人游戏,但可以在一个的设备上存储多个游戏玩家的数据。

游戏里面所有的关卡都是锁定的,只用完成当前关卡才能解锁该关卡进入下一个关卡,而每一个关卡解锁之后在这台设备上的所有玩家都可以进入。

该结构体用类型属性(Type Property)和类型方法(Type Method)来追踪游戏的关卡是否已被解锁,同时可以用来追踪单个玩家当前所在的关卡。

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
        }
    }
}

结构体LevelTracker为了便于管理和更新currentLevel属性,从而定义了这个实例方法advance(to: ), 该属性返回一个布尔值用来检查或更新当前的关卡状态。

@discardableResult 是一个attribute,它对函数,类的定义提供了一个附加信息。在本例中这个@discardableResult对结构体的实例方法(实例方法又叫类函数)做出了指明,即就算该函数的返回值不被使用,编译器也不会生成warning,

Swift 中如何使用 dispatch_after swift method_xcode

这个LevelTracker结构体被使用到Player类中,用来追踪和更新单个玩家的游戏进度。

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
    }
}

player类创建了LevelTracker的一个新实例,用来追踪玩家的进度,同时创建的新实例提供了一个complete(level:)的方法会在玩家完成某个关卡之后被调用,complete方法用来为所有玩家解锁下一关和更新玩家的进度,

var player = Player(name: "Argyrios")
player.complete(level: 1)
print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
// 输出: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")
}
// 输出:level 6 has not yet been unlocked