寒城攻略:Listo 教你 25 天学会 Swift 语言 - 13 Methods

时间:2021-09-30 19:36:07

import Foundation


//***********************************************************************************************

//1.Methods(方法)

//_______________________________________________________________________________________________

//介绍

//方法是与某些特定类型相关的函数。类,结构体,枚举都可以定义实例方法;实例方法为给定类型的实例封装了具体的任务和功能。类,结构体,枚举也可以定义类型方法,类型方法与类型本身相关联


//***********************************************************************************************

//2.Instance Methods(实例方法)

//_______________________________________________________________________________________________

//介绍

//实例方法属于某个特定类,结构体或者枚举实例。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能。


//_______________________________________________________________________________________________

//代码演示实例方法

class Counter{            //Counter 类定义了三个实例方法

   var count = 0

   func increment() -> Int {      //increment 方法让计数器按照1递增

       return ++count

    }

    func incrementBy(amount:Int) -> Int {      //incrementBy(amount: Int) 方法让计数器按照一个指定的整数值递增

       count += amount

       return count

    }

   func reset() -> Int {     //reset 将计数器重置为 0

       count = 0

       return count

    }

}

let counter =Counter()     //初始化 Counter类实例

println(counter.increment())     //调用 increment 方法

println(counter.incrementBy(5))      //调用 incrementBy(amount: Int)方法

println(counter.reset())            //调用 reset方法


//_______________________________________________________________________________________________

//方法的局部参数名称和外部参数名称

class Counter1{

   var count: Int =0

    func incrementBy(amount:Int, numberOfTimes:Int) ->Int{      //函数和方法都可以定义局部参数名和外部参数名,但是有不同点。方法定义参数时,调用方法时系统默认第一个参数为局部参数,第二个参数为外部参数,如果想让第一个参数也为外部参数,按照函数定义外部参数的方法修改即可

       count += amount * numberOfTimes

       return count

    }

}

let count1 =Counter1()

println(count1.incrementBy(2, numberOfTimes:4))


//_______________________________________________________________________________________________

//self 属性(类中每个实例都有一个隐含的属性叫做 selfself完全等同于该实例本身,我们可以在一个实例的实例方法中使用这个隐含的 self 属性来引用当前实例)

//我们一般不需要使用 self,使用 self的情况主要是当实例方法的某个参数名称与实例的某个属性名称相同的时候,在这种情况下,参数名享有优先权,并且在引用时必须使用一种严格的方式,这时我们需要 self来区分参数名称和属性名称


//_______________________________________________________________________________________________

//代码演示 self的使用环境

struct Point{

   var x = 0.0

   var y = 0.0

   func isToTheRightOfX(x: Double) -> Bool{

        returnself.x > x              //此时我们使用 self.x 来代表实例中的属性 x,而后面的 x 代表方法中的参数

    }

}

let somePoint =Point(x: 4.0, y:5.0)

if somePoint.isToTheRightOfX(1.0){

    println("This point is to the right of the line where x == 1.0")

}


//_______________________________________________________________________________________________

//使用 mutating关键字在实例方法中修改值类型(变异方法)

//结构体和枚举是值类型。一般情况下,值类型的属性不能在它的实例方法中被修改。但是,如果你确实需要在某个具体的方法中修改结构体或者枚举的属性,你可以选择变(mutating)这个方法,然后方法就可以从方法内部改变它的属性;并且它做的任何改变在方法结束时还会保留在原始结构中。方法还可以给它隐含的 self属性赋值一个全新的实例,个新实例在方法结束后将替换原来的实例

struct Point1{

   var x = 0.0, y =0.0

   mutating func moveByX(deltaX:Double, y deltaY: Double){

       x += deltaX

       y += deltaY

    }

}

var somePoint1 =Point1(x: 1.0, y:1.0)         //注意定义结构体实例时必须为变量不能为常量

somePoint1.moveByX(2.0, y:3.0)

println("The point is now at (\(somePoint1.x),\(somePoint1.y))")


//_______________________________________________________________________________________________

//在变异方法中给 self赋值

struct Point2{

   var x = 0.0

   var y = 0.0

   mutating func moveByX(deltaX:Double, y deltaY: Double){

       self = Point2(x:x + deltaX, y: y + deltaY)

    }

}

var somePoint2 =Point2(x: 1.0, y:1.0)         //注意定义结构体实例时必须为变量不能为常量

somePoint2.moveByX(2.0, y:3.0)

println("The point is now at (\(somePoint2.x),\(somePoint2.y))")


//_______________________________________________________________________________________________

//枚举的变异方法

enum TriStateSwitch{

   case Off, Low, High

    mutatingfunc next(){      //使用 mutating 定义 next 方法时,每次调用,开关在三种状态下切换

       switch self{       //这里的 self代表枚举实例

       case Off:

           self = Low

       case Low:

           self = High

       case High:

           self = Off

        }

    }

}

var ovenLight =TriStateSwitch.Low

ovenLight.next()

ovenLight.next()


//***********************************************************************************************

//3.Type Methods(类型方法)

//_______________________________________________________________________________________________

//实例方法是被类型的某个实例调用的方法。你也可以定义类型本身调用的方法,这种方法就叫做类型方法。声明类的类型方法,在方法的 func关键字之前加上关键字 class;声明结构体和枚举的类型方法,在方法的 func关键字之前加上关键字 static


//_______________________________________________________________________________________________

//代码演示类型方法声明类与类型方法的访问

class SomeClass{

   class func someTypeMethod(){

        println("this is a type method")

    }

}

SomeClass.someTypeMethod()     //直接调用类方法,在类型方法的方法体(body),self指向这个类型本身,而不是类型的某个实例


//_______________________________________________________________________________________________

//结构体与类综合演示类型方法

struct LevelTracker{                   //LevelTracker 监测玩家的已解锁的最高等级。这个值被存储在静态属性 highestUnlockedLevel

    staticvar highestUnlockedLevel =1         //定义了两个类型方法与 highestUnlockedLevel配合工作

    staticfunc unlockLevel(level:Int){       //第一个类型方法 unlockLevel:一旦新等级被解锁,它会更新 highestUnlockedLevel的值

       if level > highestUnlockedLevel{

            highestUnlockedLevel = level

        }

    }

    staticfunc levelIsUnLocked(level:Int) -> Bool{     //第二个类型方法是 levelIsUnlocked:如果某个给定的等级已经被解锁,它将返回 true

       return level <= highestUnlockedLevel

    }

    

    var currentLevel =1           //除了静态属性和类型方法,LevelTracker还监测每个玩家的进度。它用实例属性 currentLevel 来监测玩家当前的等级

    mutatingfunc advanceToLevel(level:Int) -> Bool{       //为了便于管理 currentLevel 属性,LevelTracker 定义了实例方法advanceToLevel。这个方法会在更新 currentLevel之前检查所请求的新等级是否已经解锁。advanceToLevel方法返 回布尔值以指示是否能够设置 currentLevel

       if LevelTracker.levelIsUnLocked(level){

           currentLevel = level

           return true

        }

       else{

           return false

        }

    }

}


class Player{          //Player 类使用 LevelTracker来监测和更新每个玩家的发展进度

   var tracker = LevelTracker()

   let playerName: String

   func completedLevel(level: Int){

       LevelTracker.unlockLevel(level +1)         //直接访问结构体方法

       tracker.advanceToLevel(level +1)

    }

   init(name: String){

       playerName = name

    }

}


var player =Player(name: "Listo")         //创建玩家

player.completedLevel(1)

println("highest unlocked level is now\(LevelTracker.highestUnlockedLevel)")      //此时这个结构体方法直接被调用


player =Player(name: "Pin")       //创建玩家 2

if player.tracker.advanceToLevel(6){

    println("player is now on level 6")

}

else{

    println("level 6 has not yet been unlocked")

}