The Swift Programming Language - Method（メソッド）をまとめる


[The Swift Programming Language をまとめるトップ](http://qiita.com/kiyotaman/items/052f82e9f93590b79c64)

## Properties（メソッド）
メソッドは特定の型をもつ関数
クラスや構造体や列挙型にインスタンスメソッドを定義できる
メソッドには型を定義できる
自分自身を型として関連付ける事もできる
タイプメソッドはObjCのクラスメソッドに似ている
構造体と列挙型に型を指定する事ができることが、C言語やObjCとの大きな違い
OjbCはクラスにしかメソッドを定義できなかった

### Instance Methods（インスタンスメソッド）
インスタンスメソッドはあるクラスや構造体や列挙型のインスタンスに属する
インスタンスのプロパティを編集したりインスタンスの目的を果たす為の機能を提供したりする
シンタックスは[関数セクション](http://qiita.com/kiyotaman/items/45a62bd8502df8e872ae)で説明している関数と同じ

**例**

```swift
class Counter {
    var count = 0
    func increment() {
        count++
    }
    func incrementBy(amount: Int) {
        count += amount
    }
    func reset() {
        count = 0
    }
}

let counter = Counter()
// カウンターの初期値は 0
counter.increment()
// カウントアップしてカウンターは 1
counter.incrementBy(5)
// 5カウントアップしてカウンターは 6
counter.reset()
// カウンターは 0
```

_count_ プロパティを使って、値を保持しカウンター値を操作する
メソッドはドットシンタックスで呼び出す

#### Local and External Parameter Names for Methods（メソッドのローカルと外側パラメータ名）
関数の引数はその中で使うローカル名と引数を受けるときに使う外側名前がある、[外面引数を参照](http://qiita.com/kiyotaman/items/45a62bd8502df8e872ae#3-8)
メソッドは型に紐づく関数なので、同じ動作をする
ただ、初期の動作が関数とでは多少異なる

##### for と by など
_for_ と _by_ などで終わるメソッド名にあるように、最初のパラメータはメソッド名によって分かるので、約束として外側の引数は書かない
"convention easy to write" 約束事としてのルールである

以下の例をみてみる
最初のパラメータ名はローカルでのみ有効であり、続くパラメータ名はローカルとその外側で有効な名前として引数を受ける
ObjCの動作に類似している

```swift
class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes: Int) {
        count += amount * numberOfTimes
    }
}
```

_amount_ はローカルでのみ有効であり、 _numberOfTimes_ は外側でも有効なことがわかる

```swift
let counter = Counter()
counter.incrementBy(5, numberOfTimes: 3)
// カウンターの値は 15
```

最初の引数を受ける引数名は関す名で分かるので必要ない
第二引数以降は必要になる

#### Modifying External Parameter Name Behavior for Methods（メソッドの外側引数名の変更）
（_）アンダースコアーをつかってやるらしいが、重要度が低そうなので割愛

#### The self Property（selfプロパティ）
インスタンス自体を表す _self_ があらゆるインスタンスに備わっている
_self_ そのインスタンスのメソッド等を参照している

上記のカウンターの例の続きで、以下の様に書く事もできる

```swift
func increment() {
    self.count++
}
```

ObjCとの扱いも異なり、プロパティにアクセスするときは基本的に _self_ は必要ない
直、 _method_ 内のローカル変数名とプロパティ名がかぶった時、それを見分ける為につかうことがある
以下のような感じでになる

```swift
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(1.0) {
    println("This point is to the right of the line where x == 1.0")
}
// prints "This point is to the right of the line where x == 1.0"
```

#### Modifying Value Types from Within Instance Methods（値の型をメソッド内で変更）
構造体と列挙型は _value types_ 値型で、標準でインスタンス内のメソッドでは変更できない

##### mutating
_mutating_ を func の前に設定するとメソッド経由でプロパティをメソッドの実行終了とともに更新できる

```swift
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y: 3.0)
println("pointは (\(somePoint.x), \(somePoint.y))")
// prints "pointは (3.0, 4.0)"
```

インスタンスが定数で宣言された場合、 _mutating_ があっても変更できない
_let_ は _mutating_ より強い

```swift
let fixedPoint = Point(x: 3.0, y: 3.0)
fixedPoint.moveByX(2.0, y: 3.0)
// エラーになる
```

#### Assigning to self Within a Mutating Method（selfをmutatingする）
_Mutating_ メソッドは以下のように _self_ プロパティを使って記述することもできる
以下のサンプルはその別の記述例

```swift
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }
}
```

列挙型の _mutating_ は以下の様に記述することができる

```swift
enum TriStateSwitch {
    case Off, Low, High
    mutating func next() {
        switch self {
        case Off:
            self = Low
        case Low:
            self = High
        case High:
            self = Off
        }
    }
}
var ovenLight = TriStateSwitch.Low
ovenLight.next()
// ovenLight は .High
ovenLight.next()
// ovenLight は .Off
```

_\.next()_ を使って型を移動させることができる


### Type Methods（タイプメソッド）
タイプメソッドは直接型からメソッドを呼び出す方法

#### class
クラスは _func_ の前に _class_ を付ける

#### static
構造体と列挙型は _func_ の前に _static_ を付ける

以下のように _SomeClass_ という型とドット(.)を使ってメソッドを呼び出す
シングルトンに類似している

```swift
class SomeClass {
	class func someTypeMethod() {
		// type method implementation goes here
	}
}
SomeClass.someTypeMethod()
```

_self_ プロパティ型自身を参照していて、同一クラス内のタイプメソッドを参照することができる

_LevelTracker_ ゲームをプレイしている人のレベルをトラックする
ゲーム一つにプレーイヤー一人で複数の情報をストアーする

```swift
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
        }
    }
}
```

_LevelTracker_ 構造体は一番高いレベルをとったプレイヤーのレベルを スタティックプロパティ _highestUnlockedLevel_ に保持する
タイプメソッド _unlockLevel_ は新しいレベルに到達したら解除される関数
タイプメソッド _levelIsUnlocked_ は特定のレベルがすでに解除されたかチェックする関数

構造体の中での _highestUnlockedLevel_ は _LevelTracker_ という型を指定しないでもアクセスできる
インスタンスのプロパティとして _curentLevel_ プロパティとして現在プレイ中のレベルを保持する事ができる

インスタンスメソッド _advanceToLevel_ は、 _currentLevel_ をアップデートする前にそのレベルが既に解除されたかチェックしてBooleanを返す

_LevelTracker_ 構造体は下記の様にクラス内で利用できる

```swift
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
	}
}
```

_Player_ クラスで _LevelTracker_ のインスタンスを _tracker_ として新たに生成
_Player_ クラスには _completedLevel_ メソッドがあり、プレイヤーがレベルをクリアーすると呼ばれ次のレベルを解除する
レベルが解除されたことが直前の _LevelTracker.unlockLevel_ で分かるので、 _advanceToLevel_ はのBoolean戻り値は無視される

プレイヤーごとにインスタンスをつくり、レベルをクリアすると以下のようになる

```swift
var player = Player(name: "SnapDish")
player.completedLevel(1)
println("最高レベルは \(LevelTracker.highestUnlockedLevel)")
// prints "最高レベルは 2"
```

二人目のプレイヤー

```swift
player = Player(name: "Vuzz")
if player.tracker.advanceToLevel(6) {
	println("プレイヤーはレベル 6")
} else {
	println("レベル 6 はまだ解除されていない")
}
// prints "レベル 6 はまだ解除されていない"
```