Menu

Category

Archive

logo


The Swift Programming Language ~ Methods

2014-06-17 14:00:00 +0900
  • このエントリーをはてなブックマークに追加

iBooks にある “The Swift Programming Language” の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら

今回は、Methods に関して。

Methods

メソッドは、クラス・構造体・Enumeration に関連付けされた関数です。Swift では、構造体も Enumeration もメソッドを持つことができます。また、Objective-C のクラスメソッドと似たものとして、タイプメソッドもあります。

1. Instance Methods

メソッドの定義の方法は分かり易いと思います。クラス等のタイプ宣言時にそのまま関数を定義したように書きます。

1
2
3
4
5
6
7
8
9
10
class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes: Int) {
        count += amount * numberOfTimes
    }
}

let counter = Counter()
counter.incrementBy(5, numberOfTimes: 3)
// counter value is now 15

メソッドの注意点として、まず、メソッド名は、最初の引数に関して、前置詞を付け、その引数に対して説明的にすると読みやすいです。この例では、incrementBy です。メソッド定義時には、1 つ目の引数の名前をメソッドの中で使用するために指定していますが、メソッドを呼ぶ際には必要ありません。しかし、2 つ目の引数では external name をタイプしなければなりません。

これは関数をこのように定義した時と同じ挙動です。Objective-C に慣れていれば、コードを書く際には、分かりやすいと思います。

1
2
3
func incrementBy(amount: Int, #numberOfTimes: Int) {
    count += amount * numberOfTimes
}

また、このように 1 つ目の引数に external name を付けたり、2 つ目の external name を省略することもできます。

1
2
3
4
5
6
7
8
9
class Counter {
    var count: Int = 0
    func incrementBy(a amount: Int, _ numberOfTimes: Int) {
        count += amount * numberOfTimes
    }
}

let counter = Counter()
counter.incrementBy(a: 5, 3)

メソッドの引数の名前とプロパティの名前が同じ場合には、self キーワードを使用します。そうでない場合にも、self を使用できますが、必要はありません。

1
2
3
4
5
6
7
8
9
10
11
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

2. 構造体と Enumeration の Instance Methods

構造体と Enumeration の Instance Methods は、プロパティの値をデフォルトでは、変更することができません。もし、プロパティの値をクラスのように変更したい場合には、mutating キーワードを func キーワードの前にタイプします。これにより、構造体と Enumeration においても、プロパティを変更することができるようになります。

1
2
3
4
5
6
7
8
9
10
11
12
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("The point is now at (\(somePoint.x), \(somePoint.y))")
// prints "The point is now at (3.0, 4.0)

mutating メソッドは、self に全く新しいインスタンスを代入することもできます。

1
2
3
4
5
6
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)
    }
}

これは上記でみた例と全く同じ結果を生みます。Enumeration ではこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 is now equal to .High
ovenLight.next()
// ovenLight is now equal to .Off

3. Type Methods

タイプメソッドは、Objective-C においてクラスメソッドと同じようなものです。インスタンスに、メソッドコールをするのではなく、タイプ自体 (クラス、構造体、Enumeration) に呼び出しを行います。クラスに対して、タイプメソッドを作成するには、class キーワードを、構造体・Enumeration に対して、タイプメソッドを作成するには、static キーワードを func の前に置きます。

1
2
3
4
5
6
7
8
9
10
11
12
13
class SomeClass {
    class func someTypeMethod() {
        println("Hi")
    }
}
SomeClass.someTypeMethod()

struct SomeStruct {
    static func someTypeMethod() {
        println("Hi")
    }
}
SomeStruct.someTypeMethod()

タイプメソッドの中では、そのタイプが持っている他のタイプメソッドやタイププロパティをタイプ名なしで呼び出すことができます。

1
2
3
4
5
6
struct LevelTracker {
    static var highestUnlockedLevel = 1
    static func unlockLevel(level: Int) {
        if level > highestUnlockedLevel { highestUnlockedLevel = level }
    }
}

本来、LevelTracker.highestUnlockedLevel と書きタイププロパティを参照しますが、このタイプメソッドの中では、LevelTracker というタイプ名を省略することができます。