方法是與某些特定類型相關聯的函數。類、結構體、枚舉都可以定義執行個體方法;執行個體方法為給定類型的執行個體封裝了具體的任務與功能。類、結構體、枚舉也可以定義類型方法;類型方法與類型本身相關聯。結構體和枚舉能夠定義方法是 Swift 與 C/Objective-C 的主要差別之一。
1.執行個體方法
- 執行個體方法是屬于某個特定類、結構體或者枚舉類型執行個體的方法。執行個體方法提供通路和修改執行個體屬性的方法或提供與執行個體目的相關的功能,并以此來支撐執行個體的功能。
- 執行個體方法要寫在它所屬的類型的前後大括号之間。執行個體方法能夠隐式通路它所屬類型的所有的其他執行個體方法和屬性。執行個體方法隻能被它所屬的類的某個特定執行個體調用。執行個體方法不能脫離于現存的執行個體而被調用。
//TODO:示例1
class Counter
{
var count = 0;
func increment()
{
count += 1;
}
func incrementBy(amount: Int)
{
count += amount; //沒有用self
}
//帶有局部參數名稱和外部參數名稱的方法
func incrementBy(num amount: Int, times numberOfTimes: Int)
{
self.count += amount * numberOfTimes; //用了self
}
//帶有預設外部參數名稱的方法
func incrementBy(amount: Int, numberOfTimes:Int)
{
count += amount * numberOfTimes * numberOfTimes;
}
func reset()
{
count = 0;
}
}
let counter = Counter(); // 初始計數值是0
counter.increment(); // 計數值現在是1
counter.incrementBy(3);
counter.incrementBy(5); // 計數值現在是6
counter.reset(); // 計數值現在是0
counter.incrementBy(num:2, times: 3); // 計數值現在是6
counter.reset();
counter.incrementBy(2, numberOfTimes: 3); // 計數值現在是18
//TODO:示例1說明
//1.Swift 預設僅給方法的第一個參數名稱一個局部參數名稱(沒有外部參數名稱);預設同時給第二個和後續的參數名稱局部參數名稱和外部參數名稱。
//2.如果不想為方法的第二個及後續的參數提供一個外部名稱,可以通過使用下劃線(_)作為該參數的顯式外部名稱,這樣做将覆寫預設行為。
//3.類型的每一個執行個體都有一個隐含屬性叫做self,self完全等同于該執行個體本身。可以在一個執行個體的執行個體方法中使用這個隐含的self屬性來引用目前執行個體。實際上,隻要在一個方法中使用一個已知的屬性或者方法名稱,如果沒有明确地寫self,Swift 假定是指目前執行個體的屬性或者方法。
//4.執行個體方法的某個參數名稱與執行個體的某個屬性名稱相同的時候。在這種情況下,參數名稱享有優先權,并且在引用屬性時必須使用一種更嚴格的方式。這時可以使用self屬性來區分參數名稱和屬性名稱。
//TODO:示例2
struct Point
{
var x = 0.0;
var y = 0.0;
mutating func moveByX(deltaX: Double, y deltaY: Double)
{
x += deltaX;
y += deltaY;
}
mutating func moveByPoint(deltaX: Double, y deltaY: Double) {
self = Point(x: x + deltaX, y: y + deltaY);
}
}
var somePoint = Point(x: 1.0, y: 1.0);
somePoint.moveByX(2.0, y: 3.0); //(3.0 4.0)
somePoint.moveByPoint(4.0, y: 5.0); //(7.0 9.0)
//TODO:示例2說明
//1.預設情況下,值類型(如結構體和枚舉)的屬性不能在它的執行個體方法中被修改。如果要修改,将關鍵字mutating 放到方法的func關鍵字之前就可以了。
//2.可變方法能夠賦給隐含屬性self一個全新的執行個體。
2.類型方法
- 執行個體方法是被某個類型的執行個體調用的方法。也可以定義在類型本身上調用的方法,這種方法就叫做類型方法。在方法的func關鍵字之前加上關鍵字static,來指定類型方法。類還可以用關鍵字class來允許子類重寫父類的方法實作。
//等級記錄
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 //更新目前等級之前檢查所請求的新等級是否已經解鎖
{
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);
}
init(name: String)
{
playerName = name
}
}
var player = Player(name: "Argyrios");
player.completedLevel(1);
player.tracker.advanceToLevel(6); //執行false
無善無惡心之體,
有善有惡意之動,
知善知惡是良知,
為善去惡是格物。