ジェネリック関数に加えて、Swift では独自のジェネリック型を定義することができます。あらゆる型を扱うことができるクラスや構造体、列挙型で、Array や Dictionary と同様です。

このセクションでは、ジェネリックコレクション型 Stack をどのように記述するかを示します。スタックは配列と同じような順序のある値の集合ですが、Swift の Array 型よりも操作に制限があります。配列では、配列内のどの位置に対してでも新しいアイテムを挿入あるいは削除することができます。一方でスタックでは、コレクションの最後に対してのみ新しいアイテムを追加(スタックに新しい値をプッシュ)することができます。同様に、スタックではコレクションの最後からのみアイテムを削除(スタックから値をポップ)することができます。

NOTE
スタックのコンセプトは、ビューコントローラのナビゲーション階層をモデル化する UINavigationController クラスで使用されています。ナビゲーションスタックにビューコントローラを追加(プッシュ)するために UINavigationController クラスの pushViewController(_:animated:) メソッドを、ナビゲーションコントローラからビューコントローラを削除(ポップ)するために popViewControllerAnimated(_:) メソッドを呼び出します。コレクションを管理するために厳密な「後入れ先出し」のアプローチが必要なときには、スタックは役に立つコレクションモデルです。

次の図は、スタックの push / pop の振る舞いを示しています。

image: stackPushPop_2x

  1. スタックには現在 3 つの値があります。
  2. 4 つ目の値がスタックのトップに「プッシュ」されます。
  3. この時点でスタックには値が 4つあり、最近の値がトップにあります。
  4. スタックのトップのアイテムが削除「ポップ」されます。
  5. 値をポップした後、またスタックには 3 つの値があります。

次はジェネリックでないバージョンのスタックをどのように記述するかを示していて、このケースでは Int 値のスタックです。

struct IntStack {
    var items = [Int]()
    mutating func push(item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
}

この構造体では、スタックに値を保管するために、Array プロパティ items を使用しています。Stack には、スタックに値をプッシュしポップするために、push と pop の 2 つのメソッドがあります。構造体の配列 items を変更することになるため、これらのメソッドには mutating が付けられています。

上で見た IntStack 型では Int 値のみ使用することができますが、あらゆる型の値のスタックを管理することができるジェネリックな Stack クラスを定義すればさらに有益です。

次は同じコードのジェネリックバージョンです。

struct Stack<Element> {
    var items = [Element]()
    mutating func push(item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

Stack のジェネリックバージョンは、ジェネリックでないバージョンとほとんど同じですが、実際の型 Int の代わりに、型パラメータ Element になっています。この型パラメータは、構造体の名前の直後で、山括弧内 (<Element>) に記述します。

Element は、後で提供されることになる「ある型 Element」のプレースホルダ名を定義しています。この未来の型を、構造体の定義内のどこからでも、「Element」 として参照することができます。このケースでは、Element が 3 つの場所でプレースホルダとして使用されています。

  • Element 型の値の空配列で初期化されるプロパティ items を生成するため
  • push(_:) メソッドのパラメータ item が Element 型であることを指定するため
  • pop() メソッドによって返される値が Element 型の値であることを指定するため

Stack はジェネリック型であるため、Array や Dictionary と同じようにして、Swift で有効なあらゆる型のスタックを生成するために Stack を使用することができます。

スタックで保持する型を山括弧内に記述して、新しい Stack インスタンスを生成します。例えば、文字列の新しいスタックを生成するためには、Stack<String>() と記述します。

var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// スタックには文字列が 4 つある

次の図は、スタックに 4 つの値をプッシュした後、stackOfStrings がどのようになるかを示しています。

image: stackPushedFourStrings_2x

スタックから値をポップすると、トップにある値 "cuatro" を返し、かつ削除します。

let fromTheTop = stackOfStrings.pop()
// fromTheTop は "cuatro" で、スタックには文字列が 3 つある

次の図は、トップの値をポップした後、スタックがどのようになるかを示しています。

image: stackPoppedOneString_2x


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.