インスタンスメソッドは、特定の型のインスタンスで呼び出されるメソッドです。また、型自体で呼び出せるメソッドを定義することもできます。こういったメソッドをタイプメソッドと呼びます。タイプメソッドには、メソッドの func キーワードの前に static キーワードを記述します。クラスでは、メソッドのスーパークラスでの実装を、サブクラスでオーバーライドすることを許可する class キーワードを使うこともできます。

NOTE
Objective-C では、Objective-C クラスでのみ型レベルのメソッドを定義することができます。Swift では、クラス、構造体、列挙型のすべてで型レベルのメソッドを定義することができます。各タイプメソッドはサポートする型のスコープとなります。

タイプメソッドは、インスタンスメソッドのように、ドットシンタックスで呼び出します。しかし、型のインスタンスではなく、その型でタイプメソッドを呼び出します。次の例は、SomeClass クラスでのタイプメソッドの呼び出し方です。

class SomeClass {
    class func someTypeMethod() {
        // タイプメソッドの実装
    }
}
SomeClass.someTypeMethod()

タイプメソッドの本体内では、self プロパティが型のインスタンスではなく、その型自体を参照します。構造体と列挙型では、インスタンスプロパティとインスタンスメソッドパラメータのときと同じように、self を使ってタイププロパティとタイプメソッドパラメータを区別することができます。

より一般的に、タイプメソッド内で使う限定しないメソッド名とプロパティ名は、型レベルの他のメソッドとプロパティを参照します。タイプメソッドは、型名を付ける必要なく、異なるメソッド名で別のタイプメソッドを呼び出すことができます。同様に、構造体や列挙型のタイプメソッドは、型名無しでタイププロパティの名前でタイププロパティにアクセスすることができます。

次の例では、ゲームの異なるレベルやステージについてのプレイヤーの進捗を記録する構造体 LevelTracker を定義しています。1 人用のゲームですが、1 つのデバイスで複数プレイヤーの情報を保存できます。

ゲームをはじめて遊ぶとき、ゲームのレベルはすべて(レベル 1 は別として)ロックされています。プレイヤーがレベルを完了したとき、そのレベルはデバイス上のすべてのユーザでアンロックされます。構造体 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 で保管されます。

LevelTracker は、highestUnlockedLevel プロパティを扱う 2 つのタイプ関数も定義しています。1 つ目はタイプ関数 unlockLevel で、新しいレベルがアンロックされたときに highestUnlockedLevel の値を更新します。2 つ目は便利なタイプ関数 levelIsUnlocked で、特定のレベル値がすでにアンロックされている場合に true を返します。(これらのタイプメソッドは、LevelTracker.highestUnlockedLevel と記述することなく、タイププロパティ highestUnlockedLevel にアクセスできることに注目してください。)

タイププロパティとタイプメソッドに加えて、LevelTracker は各プレイヤーのゲームの進捗を記録します。インスタンスプロパティ currentLevel を使って、プレイヤーが現在遊んでいるレベルを記録します。

currentLevel プロパティを管理するために、LevelTracker はインスタンスメソッド advanceToLevel を定義しています。currentLevel を更新する前に、このメソッドはリクエストされた新しいレベルがすでにアンロックされているかをチェックします。advanceToLevel(_:) メソッドは実際に currentLevel に設定できたか否かを示すブール値を返します。

構造体 LevelTracker は、各プレイヤーの進捗を記録、更新するために、以下に示す Player クラスで利用されます。

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 の新しいインスタンスを生成しています。completedLevel メソッドは、プレイヤーが特定のレベルを完了したときに呼び出されます。このメソッドはすべてのプレイヤーに次のレベルをアンロックします。プレイヤーの進捗を次のレベルに進めます。(前の行の LevelTracker.unlockLevel の呼び出しによってレベルがアンロックされていることがわかっているため、advanceToLevel の戻り値を無視しています。)

新しいプレイヤーのために Player クラスのインスタンスを生成することができ、プレイヤーがレベル 1 を完了したときにどうなるのかを見てみましょう。

var player = Player(name: "Argyrios")
player.completedLevel(1)
print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
// "highest unlocked level is now 2" と出力

次のプレイヤーを生成し、まだどのプレイヤーもアンロックしていないゲームレベルに進めようとした場合、プレイヤーの現在のレベルを設定しようとして失敗します。

player = Player(name: "Beto")
if player.tracker.advanceToLevel(6) {
    print("player is now on level 6")
} else {
    print("level 6 has not yet been unlocked")
}
// "level 6 has not yet been unlocked" と出力

Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.