Type Methods
实例方法是您在特定类型的实例上调用的方法。 您还可以定义在类型本身上调用的方法。 这些方法称为类型方法。 您可以通过在方法的func关键字之前写入static关键字来指示类型方法。 类可以改用class关键字,以允许子类覆盖超类对该方法的实现。
在Objective-C中,您只能为Objective-C类定义类型级别的方法。 在Swift中,您可以为所有类,结构和枚举定义类型级别的方法。 每个类型方法都明确地限定于它支持的类型。
类型方法使用点语法来调用,就像实例方法一样。 但是,您在类型上而不是在该类型的实例上调用类型方法。 在名为SomeClass的类上调用类型方法的方法如下:
class SomeClass {
class func someTypeMethod() {
// type method implementation goes here
}
}
SomeClass.someTypeMethod()
在类型方法的主体内,隐式self属性是指类型本身,而不是该类型的实例。这意味着您可以使用self来区分类型属性和类型方法参数,就像处理实例属性和实例方法参数一样。
更一般而言,在类型方法主体中使用的任何不合格的方法和属性名称都将引用其他类型级别的方法和属性。一个类型方法可以使用另一个方法的名称来调用另一个类型方法,而无需在其前面加上类型名称。同样,结构和枚举上的类型方法可以使用类型属性的名称访问类型属性,而无需使用类型名称前缀。
下面的示例定义了一个称为LevelTracker的结构,该结构可跟踪玩家在游戏的不同关卡或阶段中的进度。这是一款单人游戏,但可以在单个设备上存储多个玩家的信息。
首次玩游戏时,所有游戏级别(除了第一级)都被锁定。每次玩家完成一个关卡时,设备上的所有玩家都将解锁该关卡。 LevelTracker结构使用类型属性和方法来跟踪游戏的哪些级别已解锁。它还跟踪单个玩家的当前级别。
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结构跟踪所有玩家已解锁的最高级别。此值存储在名为maximumUnlockedLevel的类型属性中。
LevelTracker还定义了两个类型函数,以与highestUnlockedLevel属性一起使用。第一个是称为unlock(_ :)的类型函数,每当解锁新级别时,该函数都会更新highestUnlockedLevel的值。第二个是便捷类型函数,称为isUnlocked(_ :),如果特定级别的数字已被解锁,则返回true。 (请注意,这些类型方法可以访问maximumUnlockedLevel类型属性,而无需将其编写为LevelTracker.highestUnlockedLevel。)
除了其type属性和type方法之外,LevelTracker还可以跟踪单个玩家在游戏中的进度。它使用称为currentLevel的实例属性来跟踪玩家当前正在玩的级别。
为了帮助管理currentLevel属性,LevelTracker定义了一个称为advance(to :)的实例方法。在更新currentLevel之前,此方法检查所请求的新级别是否已被解锁。 advance(to :)方法返回一个布尔值,以指示它是否实际上能够设置currentLevel。由于调用先进方法(to :)忽略返回值不一定是错误的代码,因此此函数标有@discardableResult属性。有关此属性的更多信息,请参见属性。
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 :)的方法,每当玩家完成特定级别时就会调用该方法。 此方法为所有玩家解锁下一个级别,并更新玩家的进度以将他们移至下一个级别。 (Advance(to :)的布尔返回值将被忽略,因为已知该级别已通过调用上一行的LevelTracker.unlock(_ :)进行了解锁。)
您可以为新玩家创建Player类的实例,并查看该玩家完成第一级后会发生什么:
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"