LoginSignup
33
32

More than 5 years have passed since last update.

The Swift Programming Language - Method(メソッド)をまとめる

Last updated at Posted at 2014-06-09

The Swift Programming Language をまとめるトップ

Properties(メソッド)

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

Instance Methods(インスタンスメソッド)

インスタンスメソッドはあるクラスや構造体や列挙型のインスタンスに属する
インスタンスのプロパティを編集したりインスタンスの目的を果たす為の機能を提供したりする
シンタックスは関数セクションで説明している関数と同じ

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(メソッドのローカルと外側パラメータ名)

関数の引数はその中で使うローカル名と引数を受けるときに使う外側名前がある、外面引数を参照
メソッドは型に紐づく関数なので、同じ動作をする
ただ、初期の動作が関数とでは多少異なる

for と by など

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

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

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

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

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

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

Modifying External Parameter Name Behavior for Methods(メソッドの外側引数名の変更)

(_)アンダースコアーをつかってやるらしいが、重要度が低そうなので割愛

The self Property(selfプロパティ)

インスタンス自体を表す self があらゆるインスタンスに備わっている
self そのインスタンスのメソッド等を参照している

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

func increment() {
    self.count++
}

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

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 の前に設定するとメソッド経由でプロパティをメソッドの実行終了とともに更新できる

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 があっても変更できない
letmutating より強い

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 プロパティを使って記述することもできる
以下のサンプルはその別の記述例

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 は以下の様に記述することができる

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 という型とドット(.)を使ってメソッドを呼び出す
シングルトンに類似している

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

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

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

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 は特定のレベルがすでに解除されたかチェックする関数

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

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

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

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戻り値は無視される

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

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

二人目のプレイヤー

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
32