執行個體方法是被某個類型的執行個體調用的方法,類型方法是定義在類型本身上調用的方法。
執行個體方法
屬于某個特定類、結構體或者枚舉類型執行個體的方法。提供通路和修改執行個體屬性的方法或提供與執行個體目的相關的功能,并以此來支撐執行個體的功能。
執行個體方法能夠隐式通路它所屬類型的所有的其他執行個體方法和屬性。隻能被它所屬的類的某個特定執行個體調用,并且不能脫離于現存的執行個體而被調用。
class Counter {
var count = 0
//執行個體方法
func increment() {
count += 1
}
func increment(by amount: Int) {
count += amount
}
func reset(){
count = 0
}
}
let counter = Counter()
counter.increment() //起始值是0,現在是1
counter.increment(by: 5) //現在是6
counter.reset() //現在是0
self屬性
使用 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") //This point is to the right of the line where x == 1.0
}
說明:如果不使用 self 字首,Swift會認為 x 的兩個用法都引用了名為 x 的方法參數。
在執行個體方法中修改值類型(mutating)
預設情況下,值類型的屬性不能在它的執行個體方法中被修改。
但是,如果确實需要在某個特定的方法中修改結構體或者枚舉的屬性,可以為這個方法選擇可變(mutating)行為,然後就可以從其方法内部改變它的屬性;并且這個方法做的任何改變都會在方法執行結束時寫回到原始結構中。方法還可以給它隐含的 self 屬性賦予一個全新的執行個體,這個新執行個體在方法結束時會替換現存執行個體。
struct Point1 {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var somePoint1 = Point1(x: 1.0, y: 1.0)
somePoint1.moveBy(x: 2.0, y: 3.0)
print("The point is now at (\(somePoint1.x), \(somePoint1.y))") //3.0,4.0
注:不能在結構體類型的常量上調用可變方法,因為其屬性不能被改變,即使屬性是變量屬性.
在可變方法中給 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() //high
ovenLight.next() //off
類型方法
在方法的 func 關鍵字之前加上關鍵字 static,來指定類型方法。類還可以用關鍵字 class 來指定,進而允許子類重寫父類該方法的實作。
struct LevelTracker {
static var highestUnlockedlevel = 1
var currentLevel = 1 //玩家進度
//新等級被解鎖,更新 highestUnlockedlevel
static func unlock(_ level: Int) {
if level > highestUnlockedlevel {
highestUnlockedlevel = level
}
}
//給定等級已解鎖,傳回true
static func isUnlocked(_ level: Int) -> Bool {
return level <= highestUnlockedlevel
}
//更新前檢查新等級是否解鎖
@discardableResult //允許在調用 advance(to:) 時候忽略傳回值,不會産生編譯警告
mutating func advance(to level: Int) -> Bool {
if LevelTracker.isUnlocked(level) {
currentLevel = level
return true
}else {
return false
}
}
}
//Player 類使用 LevelTracker 來監測和更新每個玩家的發展進度
class Player {
var tracker = LevelTracker()
let palyerName: String
func complete(level: Int) {
LevelTracker.unlock(level + 1)
tracker.advance(to: level + 1)
}
init(name: String){
palyerName = name
}
}
var player = Player(name: "Argyrios")
player.complete(level: 1)
print("highest unlocked level is now \(LevelTracker.highestUnlockedlevel)") //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")
}