swift 筆記 (十一) —— 方法(類,結構體,枚舉)

來源:互聯網
上載者:User

標籤:定義   結構體   使用   sel   next   nal   switch   執行個體   color   

Methods (方法)
執行個體方法(Instance Methods)我認為看到這裡。我們唯能八一八的就是swift的自做主張的行為了,反正它就是會以各種方式協助我們來完畢讓代碼看起來非常奇怪的事情。。。
在之前函數那一篇筆記中,我們已經看到過參數的外部名字和內部名字的區分了,當然。在執行個體方法中,這個事情依舊存在,並且。swift又會幫我們做一些潛規則。
swift在預設的情況下,會為方法的第一個參數僅僅提供函數內部使用的名字,而從第二個參數開始,既能夠外部用,也能夠內部用(就像我們在函數中見過的  External Parameter 一樣):
class MyClass{     var myNum: Int = 0     func increaseNum(base: Int, numberOfTimes: Int) {          myNum += base * numberOfTimes     }}
var myClassInstance = MyClass()myClassInstance.increase(10, numberOfTime: 8)   //第二個參數開始,會自己主動的提供一個外部使用變數名 (感謝 swift技術交流第一平台(355277)的群友 偏未晚(1027115179) 指出錯這裡的函數名筆誤 )
myClassInstance.increaseNum(10, numberOfTime: 8)   //第二個參數開始,會自己主動的提供一個外部使用變數名

這就相當於。我們在函數那部分提到的函數想為外部提供一個變數名的話,有兩種做法:1.  func myFunc(value paramA: Int)  {……}    //value是給外部用的名字, paramA是給內部用的2.  func myFunc(#paramA: Int) {……}     //paramA 既是外部用的,也是內部用的
而在上面的MyClass類的執行個體方法中。相當於,從第二個參數開始。swift自己主動為我們提供人了”#”的功能。而不須要我們明白的寫#這個預設的行為,有時候是很討厭的,所以swift依舊提供給我們不給外部提供名字的方法:class MyClass{     var myNum: Int = 0     func increaseNum(base: Int, _ numberOfTimes: Int) {      //注意這一行有一個 “_"          myNum += base * numberOfTimes     }} 
在參數的名字前面加了一個”_”和一個空格,這樣,swift便不再會自己主動提供外部使用名字了。

當然。假設我們把”_”這裡,換成別的名字,那麼就跟之前說的函數是一樣的了。


self 屬性每一個執行個體。都有一個屬性用於表示它自己這個執行個體。這個屬性叫做self。class MyClass{     var  num: Int = 0     func setNum(num:Int) {          self.num = num            //注意這裡的self     }} 假設出現這個setNum方法的情況,傳入的參數名叫num, 而我們設定的屬性也叫num的時候,為了區分,究竟是傳入的值還是執行個體的屬性。我們為執行個體屬性前面加了self,表示是這個執行個體自己的屬性。


Mutating方法以上面說的都是類的情況。那麼對於 struct, enum這種值傳遞類型,卻不能使用執行個體方法來改變屬性的值。

struct MyPoint {     var x = 0, y = 0     mutating func moveByXY(deltaX: Int, y deltaY: Int) {    //注意這裡的mutatingkeyword          x += deltaX          y += deltaY     }}
var instance = MyPoint()instance.moveByXY(3, y: 4)println(“x:\(instance.x)  y:\(instance.y)”)在struct, enum裡使用mutatingkeyword,以達到和class裡一樣的效果注意:假設上面的x,和y 不是var,而是let的話,是不能用的,由於我們不能改變一個常量的值。
在Mutating方法中,給self賦值struct MyPoint {     var x = 0, y = 0     mutating func changeSelf(deltaX: Int, y deltaY: Int) {          self = MyPoint (x: deltaX, y: deltaY)      //注意這裡的selfkeyword     }} 
var instance = MyPoint()instance.changeSelf(3, y: 4)println(“x:\(instance.x)  y:\(instance.y)”)
這樣的方式,也相同達到了改變 instance中的x和y的目的,然而,這樣的給self賦值的方法。卻是產生了一個新的MyPoint的執行個體(而之前的執行個體是怎樣銷毀的。記憶體怎樣釋放的。要等到後面講到記憶體管理的章節才幹說到,這裡臨時不考慮)
enum MyStateMachine {     case None, Init, Run, Deinit     mutating func nextState() {          switch self {               case None:                    self = Init               case Init:                    self = Run               case Run:                    self = Deinit               case Deinit:                    self = None          }     }}
var stateMachine = MyStateMachine.NonestateMachine.nextState()                                        //self變成 Initprintln(stateMachine == MyStateMachine.Init)          // true
stateMachine.nextState()                                        //self 變成 Runprintln(stateMachine == MyStateMachine.Init)          //true
這就非常有意思了,狀態機器的狀態切換的代碼能夠直接寫在enum的定義中
類型方法上面提到的方法。都是執行個體相關的方法,它們都是針對某一個執行個體進行操作的,而類型方法,是對於這個類型的,事實上這樣的方法在上一篇筆記中,類型屬性的那部分已經出現過keyword了:static和class。


class MyClass {     class var computedProperty: Int {          //這是一個類型屬性,上一篇筆記中提到的
     }
     class func someMethod() {                    //這才是一個類型方法
     }}
由於類裡面的類型屬性只能用於計算。不能儲存資料。所以類裡的類型方法,臨時還不適合寫一個能夠跑起來的範例,應該結合struct 或者enum,才幹夠寫,還是先看看struct的類型方法吧,enum和struct差點兒相同(這是個官方範例, 方便複製就不帖圖了。不過抄了一遍。由於我非常喜歡這個範例,在實際的遊戲開發中非經常常使用):
struct LevelTracker {     static var highestUnlockedLevel = 1                       //類型屬性。全部的執行個體共用這個值     static func unlockLevel(level: Int) {                         //類型方法          if level > highestUnlockedLevel {               highestUnlockedLevel = level          }     }
     static func levelIsUnlocked(level: Int) -> Bool {          //類型方法          return level <= highestUnlockedLevel     }
     var currentLevel = 1
     mutating func advanceToLevel(level: Int) -> Bool {               //Mutating方法,是個執行個體方法          if LevelTracker.levelIsUnlocked(level) {               currentLevel = level               return true          } else {               return false          }     }}
class Player {     var tracker = LevelTracker()          //上面定義的結構體的一個執行個體     let playerName: String     func completedLevel( level: Int) {          LevelTracker.unlockLevel(level + 1)          //調用了上面那個結構體的類型方法          tracker.advanceToLevel(level + 1)             //調用了tracker這個執行個體的Mutating方法(執行個體方法)     }
     init(name: String) {          playerName = name                  //關於這個playerName常量初始化問題,在後面的章節會提到     }}
var player = Player(name: “World”)player.completedLevel(1)                    //這個函數調用後 tracker的highestUnlockedLevel 會變成2
println(“highest unlocked  level is now \(LevelTracker.highestUnlockedLevel)”)
var player2 = Player(name: “Kitty”)if player2.tracker.advanceToLevel(6) {          //檢測能否夠把player2設定為6級     println(“player is now on level6")} else {     println(“level 6 has not yet been unlocked")}
執行結果是else中的println被執行。這個範例,假設上面的內容都看懂了的話,讀起來應該非常easy。假設還是不懂,那麼請回結合上一篇筆記一起看。

swift 筆記 (十一) —— 方法(類,結構體,枚舉)

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.