在Swift語言中,方法分兩種:
- 實例方法,為給定類型的實例封裝 了具體的任務與功能,通過實例對象來調用;
- 類型方法,和類型本身相關聯(lián),通過類型名稱來調用。
方法(Method)使用適用于類、結構體和枚舉。
結構體和枚舉能夠定義方法是
Swift與C/Objective-C的主要區(qū)別之一。在Objective-C中,類是唯一能定義 方法的類型。但在Swift中,你不僅能選擇是否要定義一個類/結構體/枚舉,還能靈活地在你創(chuàng)建的類型(類/ 結構體/枚舉)上定義方法。
實例方法(Instance Methods)
- 實例方法是屬于某個特定類、結構體或者枚舉類型實例的方法。實例方法提供訪問和修改實例屬性的方法或提供
與實例目的相關的功能,并以此來支撐實例的功能。
- 實例方法是屬于某個特定類、結構體或者枚舉類型實例的方法。實例方法提供訪問和修改實例屬性的方法或提供
- 實例方法要寫在它所屬的類型的前后大括號之間。實例方法能夠隱式訪問它所屬類型的所有的其他實例方法和屬
性。實例方法只能被它所屬的類的某個特定實例調用。實例方法不能脫離于現(xiàn)存的實例而被調用。
- 實例方法要寫在它所屬的類型的前后大括號之間。實例方法能夠隱式訪問它所屬類型的所有的其他實例方法和屬
如下例子
class StepCounter
{
var stepCount = 0
func increasement()
{
stepCount += 1
}
func increasemen(by amount:Int)
{
stepCount += amount;
}
func resetCount()
{
stepCount = 0
}
}
let counter = StepCounter.init()
for _ in 1...10
{
counter.increasement()
}
print("-01-stepCounter = \(counter.stepCount)")
counter.increasemen(by: 100)
print("-02-stepCounter = \(counter.stepCount)")
counter.resetCount()
print("-03-stepCounter = \(counter.stepCount)")
輸出結果
-01-stepCounter = 10
-02-stepCounter = 110
-03-stepCounter = 0
Program ended with exit code: 0
如上,和屬性一樣,我們可以使用.語法(dot syntax)來調用實例方法。
1. self屬性
類型的每一個實例都有一個隱含屬性叫做self, self 完全等同于該實例本身。你可以在一個實例的實例方法中 使用這個隱含的self屬性來引用當前實例.如下,increasement()還可以這樣寫,
func increasement()
{
self.stepCount += 1
}
在項目我們不必經(jīng)常寫self.,不過當參數(shù)名和屬性名稱一樣的情況下,參數(shù)名稱享有優(yōu)先權,并且在引用屬性時必須使用一種更嚴格的方式。這時你可以使用self屬性來區(qū)分參數(shù)名稱和屬性名稱。
如下
func increasemen(by stepCount:Int)
{
self.stepCount += stepCount;
}
2. 在實例方法中修改值類型
結構體和枚舉是值類型。默認情況下,值類型的屬性不能在它的實例方法中被修改。但是,如果我們需要在某個特定的方法中修改結構體或者枚舉的屬性,可以為這個方法設置可變(mutating) 行為,然后就可以從其方法內部改變它的屬性,并且這個方法做的任何改變都會在方法執(zhí)行結束時寫回到原始結構中。方法還可以給它隱含的self屬性賦予一個全新的實例,這個新實例在方法結束時會替換現(xiàn)存實例。
如下例子
struct MyPoint
{
var x = 0.0
var y = 0.0
mutating func moveByX(typeX:Double,typeY:Double)
{
self.x += typeX
self.y += typeY
}
}
var point = MyPoint.init(x: 10, y: 10)
print("MyPoint = \(point.x,point.y)")
point.moveByX(typeX: 11, typeY: 11)
print("Now,MyPoint = \(point.x,point.y)")
運行結果
MyPoint = (10.0, 10.0)
Now,MyPoint = (21.0, 21.0)
Program ended with exit code: 00
注意:不能在結構體類型的常量(a constant of structure type)上調用可變方法,因為其屬性不能被改變,即使屬性是變量屬性.eg.let point02 = MyPoint.init(x: 10, y: 10) ,point02就不能修改其屬性的值。
3. 在可變方法中給Self賦值
可變方法能夠賦給隱含屬性 self一個全新的實例,上面MyPoint的例子還可以如下寫
struct MyPoint
{
var x = 0.0
var y = 0.0
mutating func moveByX(typeX:Double,typeY:Double)
{
self = MyPoint.init(x: self.x + typeX, y: self.y + typeY)
}
}
var point = MyPoint.init(x: 10, y: 10)
print("MyPoint = \(point.x,point.y)")
point.moveByX(typeX: 11, typeY: 11)
print("Now,MyPoint = \(point.x,point.y)")
在枚舉的可變方法中,我們可以把self設置為同一枚舉類型的不同成員,如下
enum SwitchType
{
case Off,Low,High
mutating func nextType()
{
switch self
{
case .Off:
self = .Low
case .Low:
self = .High
case .High:
self = .Off
}
}
}
var lightingSwitchType = SwitchType.Off
lightingSwitchType.nextType()
print(lightingSwitchType)
lightingSwitchType.nextType()
print(lightingSwitchType)
運行結果:
Low
High
Program ended with exit code: 0
類型方法(Type Methods)
- 類型方法是定義在類型本身上調用的方法,這一點和
Objective-C中的靜態(tài)方法類似,都是通過類型名來調用該方法。
- 類型方法是定義在類型本身上調用的方法,這一點和
-
在方法的
func關鍵字之前加上關鍵字static,來指定類型方法。類還可以用關鍵字class來允許子類重寫 父類的方法實現(xiàn)。
-
在方法的
- 在
Objective-C中,你只能為Objective-C的類類型(classes)定義類型方法(type-level methods)。在Swift中,你可以為所有的類、結構體和枚舉定義類型方法。每一個類型方法都被它所支持的類型顯式包含。
- 在
如下例子
class MyTestClass
{
class func testTypeClassFunc()
{
print("這是一個類型方法!")
}
static func testSubSuperClassFunc()
{
print("這是一個類型方法,子類重寫父類方法!")
}
}
MyTestClass.testTypeClassFunc()
MyTestClass.testSubSuperClassFunc()
運行結果
這是一個類型方法!
這是一個類型方法,子類重寫父類方法!
Program ended with exit code: 0
- 在類型方法的方法體(
body)中,self指向這個類型本身,而不是該類型的某個實例。這意味著我們可以用self來消除類型屬性和類型方法參數(shù)之間的歧義,類似于上面處理實例屬性和實例方法參數(shù)時的做法。
- 在類型方法的方法體(
- 一般來說,在類型方法的方法體中,任何未被限定的方法和屬性名稱,可以被本類中的其它類型方法和類型屬性引用;一個類型方法可以通過類型方法名稱直接調用本類中的其它類型方法,不用直接通過類型名來調用;在結構體和枚舉中,也能夠直接通過類型屬性的名稱訪問本類中的類型屬性,而不需要前面加上類型名稱。
請看下面的例子
struct LevelTracker
{
static var highestUnLockLevel = 1//檢測玩家已經(jīng)解鎖的最高等級(類型屬性)
var currentLevel = 1//檢測每個玩家當前的等級
static func unlock(_ level:Int)//一旦新等級被解鎖,該函數(shù)就會更新highestUnLockLevel的值
{
if level > highestUnLockLevel
{
highestUnLockLevel = level
}
}
/*
*如果給定Level值<=highestUnLockLevel,說明該等級已經(jīng)被解鎖,就會返回true
*/
static func isUnlocked(_ level:Int) -> Bool
{
return level <= highestUnLockLevel
//也可以用下面的樣式來寫
//return level <= highestUnLockLevel ?true:false
}
/*
*函數(shù)被標注為 @ discardableResult,允許在調用函數(shù)時候忽略返回值
*更新currentLevel之前,判斷等級是否已經(jīng)解鎖,如果解鎖就能設置currentLevel
*/
@discardableResult
mutating func advance(to level:Int) -> Bool
{
if LevelTracker.isUnlocked(level)
{
currentLevel = level
return true
}
else
{
return false
}
}
}
class Player
{
var tracker = LevelTracker()
let playerName:String
/*complete(level:)
*一旦玩家完成某個指定等級就會調用它
*并且為當前所有玩家解鎖下一等級,將當前玩家的等級更新為下一級
*/
func complete(level:Int)
{
LevelTracker.unlock(level + 1)
tracker.advance(to: level + 1)
}
init(name:String)
{
playerName = name
}
}
var player = Player.init(name: "TestDemo")
player.complete(level: 1)
print("當前最高等級為:\(LevelTracker.highestUnLockLevel)")
var player2 = Player.init(name: "Hahaha")
if player2.tracker.advance(to: 8)
{
print("等級解鎖成功,玩家當前等級為:\(LevelTracker.highestUnLockLevel)")
}
else
{
print("等級解鎖失敗")
}
運行結果
當前最高等級為:2
等級解鎖失敗
Program ended with exit code: 0
在上面的例子中,
LevelTracker是游戲玩家的等級模型,highestUnLockLevel為當前游戲所有玩家中已經(jīng)解鎖的最高等級,currentLevel為每個玩家的當前等級;- 一旦新等級被解鎖,就會通過
unlock(_ level:Int)方法來更新highestUnLockLevel的值;同時會通過isUnlocked(_ level:Int)方法來判斷一個給定的等級是否已經(jīng)被解鎖;advance方法的作用請參考注釋。Player類為一個游戲玩家模型。當我們試圖給player2對象設置一個還未被解鎖的等級時,就會提示解鎖失敗。