swift 学习- 12 -- 方法
// 方法 是與某些特定類型相關的函數.? 類, 結構體,枚舉 都可以定義實例方法, 實例方法為給類型的實例封裝了具體的任務與功能.? 類, 結構體, 枚舉 也可以定義類型方法,? 類型方法與類型本身相關聯, 類型方法與 OC 中的 類方法 類似
?
// 結構體和枚舉 能夠定義方法 是 swift 與 C語言 和 OC 的主要區別之一, 在 OC? 中, 類是唯一能定義方法的類型, 但是在 Swift 中, 你能靈活地在你創建的類型(類/ 結構體/ 枚舉) 上定義方法
?
?
?
// 實例方法
// 實例方法是屬于某個特定 類, 結構體 或 枚舉類型實例的方法, 實例方法提供訪問和修改實例屬性的方法 或 提供與實例目的相關的功能, 并以此來支撐實例的功能, 實例方法的語法與函數完全一致
?
// 實例方法要寫在它所屬的類型的前后大括號之間, 實例方法能夠隱式訪問它所屬類型的所有的其他實例方法的屬性, 實例方法只能被他所屬的類的某個特定實例調用, 實例方法不能脫離于現存的實例而被調用
?
class Counter{
? ? var count = 0
? ? func increment() -> Void {
? ? ? ? self.count += 1
? ? }
?? ?
? ? func increment(by amount: Int) -> Void {
? ? ? ? count += amount
? ? }
?? ?
? ? func reset() -> Void {
? ? ? ? count = 0
? ? }
}
?
// Counter 這個類還聲明了一個可變屬性 count, 用它來保持對當前計數器值的跟蹤
// 和調用屬性一樣, 用點語法調用 實例方法
?
let counter = Counter()
print(counter.count)
?
counter.increment()
print(counter.count)
?
counter.increment(by: 5)
print(counter.count)
?
counter.reset()
print(counter.count)
?
// 函數參數可以同時有一個局部名稱 (在函數內部使用) 和一個外部名稱 (在調用函數時使用),方法參數也一樣, 因為方法就是函數, 只是這個函數與某個類型相關聯了
?
?
?
?
// self 屬性
// 類型的每一個實例都有一個隱含屬性叫做 self , self 完全等于該實例本身, 你可以在一個實例的實例方法中使用這個隱含的 self 屬性來引用當前實例
?
// 上面的例子還可以這么寫
// func increment() {
// ? ? self.count += 1
// }
?
?
// 實際上, 你不必在你的代碼中經常寫 self,不論何時,只要在一個方法中使用一個已知的屬性或者方法名稱,. 如果你沒有明確的寫 self, Swift 假定你是指當前實例的屬性或者方法
?
// 使用這條規則的主要場景是實例方法的某個參數與實例的某個屬性名稱相同的時候, 在這種情況下, 參數名稱享有優先權, 并且在引用屬性時必須使用一種更嚴格的方式, 這時你可以使用 self 屬性來區分參數名稱和屬性名稱
?
struct Point{
? ? var x = 0.0, y = 0.0
? ? func isToTheRightOfX(x: Double) -> Bool {
? ? ? ? return self.x > x
? ? }
}
?
let somePoint = Point(x:4.0,y:5.0)
if? somePoint.isToTheRightOfX(x: 1.0) {
? ? print("This point is the right of the line where x == 1.0")
}
?
// 如果不使用 self 前綴, Swift 就認為兩次使用的 x 都指的是名稱為 x 的函數參數
?
?
?
?
// 在實例方法中修改值類型
// 結構體和枚舉是值類型, 默認情況下,值類型的屬性不能在他的實例方法中被修改
?
// 但是, 如果你確實需要在某個特定的方法中修改結構體或者枚舉的屬性, 你可以為這個方法選擇 可變(mutating)行為, 然后就可以從其方法內部改變它的屬性, 并且這個 方法 做的任何改變 都會在執行結束時 寫回到 原始結構體中, 方法還可以給它隱含的 self 屬性賦予一個全新的實例, 這個心實例在方法結束時會替換現有的實例
?
struct PointTwo{
? ? var x = 0.0,y = 0.0
? ? mutating func moveByX(deltaX: Double, y deltaY: Double){
? ? ? ? x += deltaX
? ? ? ? y += deltaY
? ? }
}
?
var somePointTwo = PointTwo(x:1.0,y:1.0)
somePointTwo.moveByX(deltaX: 2.0, y: 3.0)
?
print("The point is now at (\(somePointTwo.x), \(somePointTwo.y))")
?
// 上面的 point 結構體定義了一個可變方法 moveByX(_:y:) 來移動 Point 實例到給定的位置, 該方法被調用時修改了這個點, 而不是返回了一個新的點, 方法定義時加上 mutating 關鍵字, 從而允許修改屬性
?
// 注意 : 不能在 結構體類型的常量 上調用可變的方法, 因為其屬性不能被改變,即使屬性是變量屬性
?
?
?
?
?
// 在可變方法中給 self 賦值
// 可變方法能夠賦給隱含屬性 self 一個全新的實例, 上面的 pointTwo 可以改寫為:
?
struct PointThree{
? ? var x = 0.0, y = 0.0
? ? mutating func moveBy(x deltaX: Double, y deltaY: Double){
? ? ? ? self = PointThree(x: x + deltaX, y: y + deltaY)
? ? }
}
?
// 新版的可變方法 moveBy(x:y:) 創建了一個新的結構體實例, 它的 x 和 y 的值都被設定為目標值, 調用這個版本的方法調用上個版本的最終結果是一樣的
?
// 枚舉的可變方法可以把 self 設置為同一枚舉類型中不同的成員
?
enum TriStatrSwitch {
? ? case Off, Low, High
? ? mutating func next(){
? ? ? ? switch self {
? ? ? ? case .Off:
? ? ? ? ? ? self = .Low
? ? ? ? case .Low:
? ? ? ? ? ? self = .High
? ? ? ? case .High:
? ? ? ? ? ? self = .Off
? ? ? ? }
? ? }
}
?
var ovenLight = TriStatrSwitch.Low
ovenLight.next()
print(ovenLight)
?
?
?
?
// 類型方法
// 類型方法是被某個類型的實例調用的方法, 你可以定義在類型本身調用的方法,這種方法就叫做 類型方法 , 在方法的 func 關鍵字之前加上 static ,用來指定類型方法. 類還可以用關鍵字 class 來允許子類重寫父類的方法實現
?
// 注意: 在 OC 中, 你只能為 OC 的類類型(classes) 定義類型方法 (type-level methods), 在 Swift 中, 你可以為所有的類, 結構體 和 枚舉 類型定義類型方法, 每一個類型方法都被它所支持的類型顯式包含
?
// 類型方法和實例方法一樣用點語法調用, 但是, 你是在類型上調用這個方法, 而不是在實例上調用, 如下例子:
?
class SomeClass{
? ? class func someTypeMethod() {
? ? ? ? // 在這里實現類型方法
? ? }
}
?
// 在類型方法的方法體中, self 指向這個類型本身, 而不是類型的某個實例, 這意味著你可以用 self 來消除類型屬性 和 類型方法參數之間的歧義,
// 一般來說, 在類型方法的方法體中, 任何未限定的方法和屬性名稱, 可以被本類中其它的類型方法和類型屬性引用, 一個類型方法 可以直接通過 類型方法的名稱 調用其它類型方法, 而無需在方法名稱前面加上 類型名稱, 類似的, 在結構體中 和 枚舉中, 也能夠直接通過類型屬性的名稱訪問本類中的類型屬性, 而不需要前面加上類型名稱
?
// 下面的例子定義了一個名為LevelTracker結構體。它監測玩家的游戲發展情況(游戲的不同層次或階段)。這是一個單人游戲,但也可以存儲多個玩家在同一設備上的游戲信息。
?
// 游戲初始時,所有的游戲等級(除了等級 1)都被鎖定。每次有玩家完成一個等級,這個等級就對這個設備上的所有玩家解鎖。LevelTracker結構體用類型屬性和方法監測游戲的哪個等級已經被解鎖。它還監測每個玩家的當前等級。
?
struct LevelTracker {
? ? static var highesUnlockedLevel = 1
? ? var currentLevel = 1
?? ?
? ? static func unlock(_ level: Int){
? ? ? ? if level > highesUnlockedLevel {
? ? ? ? ? ? highesUnlockedLevel = level
? ? ? ? }
? ? }
?? ?
? ? static func isUnlocked(_ level: Int) -> Bool{
? ? ? ? return level <= highesUnlockedLevel
? ? }
?? ?
? ? @discardableResult
? ? mutating func advance(to level: Int) -> Bool {
? ? ? ? if LevelTracker.isUnlocked(level) {
? ? ? ? ? ? currentLevel = level
? ? ? ? ? ? return true
? ? ? ? } else {
? ? ? ? ? ? return false
? ? ? ? }
? ? }
}
?
// LevelTracker監測玩家已解鎖的最高等級。這個值被存儲在類型屬性highestUnlockedLevel中。
?
// LevelTracker還定義了兩個類型方法與highestUnlockedLevel配合工作。第一個類型方法是unlock(_:),一旦新等級被解鎖,它會更新highestUnlockedLevel的值。第二個類型方法是isUnlocked(_:),如果某個給定的等級已經被解鎖,它將返回true。(注意,盡管我們沒有使用類似LevelTracker.highestUnlockedLevel的寫法,這個類型方法還是能夠訪問類型屬性highestUnlockedLevel)
?
// 除了類型屬性和類型方法,LevelTracker還監測每個玩家的進度。它用實例屬性currentLevel來監測每個玩家當前的等級。
?
// 為了便于管理currentLevel屬性,LevelTracker定義了實例方法advance(to:)。這個方法會在更新currentLevel之前檢查所請求的新等級是否已經解鎖。advance(to:)方法返回布爾值以指示是否能夠設置currentLevel。因為允許在調用advance(to:)時候忽略返回值,不會產生編譯警告,所以函數被標注為@ discardableResult屬性,更多關于屬性信息,請參考屬性章節。
?
// 下面,Player類使用LevelTracker來監測和更新每個玩家的發展進度:
?
class Player{
? ? var tracker = LevelTracker()
? ? let playerName: String
? ? func complete(level: Int) {
? ? ? ? LevelTracker.unlock(level + 1)
? ? ? ? tracker.advance(to: level + 1)
? ? }
?? ?
? ? init(name: String) {
? ? ? ? self.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)")
// 打印 "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"
?
轉載于:https://www.cnblogs.com/dingzhijie/p/6894399.html
總結
以上是生活随笔為你收集整理的swift 学习- 12 -- 方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle查看用户密码时间限制
- 下一篇: Gson转换 — json数据转换为Ob