Generics 総称体

Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner. 総称体コードは、あなたに柔軟な、再使用できる関数と型を書くことを可能にします、それは、あなたが定義する要件を満たした場合に限り、あらゆる型を扱うことができます。あなたは、重複を避けて、明快な、抽象化された手法で、その意図を表すコードを書くことができます。

Generics are one of the most powerful features of Swift, and much of the Swift standard library is built with generic code. In fact, you’ve been using generics throughout the Language Guide, even if you didn’t realize it. For example, Swift’s Array and Dictionary types are both generic collections. You can create an array that holds Int values, or an array that holds String values, or indeed an array for any other type that can be created in Swift. Similarly, you can create a dictionary to store values of any specified type, and there are no limitations on what that type can be. 総称体は、スウィフトの最も強力な特徴のうちの1つです、そして、多くのスウィフト標準ライブラリは総称体コードで組み立てられます。実際、たとえあなたがそれを実感しなかったとしても、あなたはこの言語ガイドを通して総称体を使用していました。例えば、スウィフトのArrayDictionary型は、両方とも総称体コレクションです。あなたは、Int値を保持する配列、またはString値を保持する配列、またはそれどころかスウィフトで作成可能なあらゆる他の型のためにも配列をつくることができます。同じように、あなたはどんな指定された型の値それらでも保管する辞書を作成することができます、そしてその型が何であることができるか制限がありません。

The Problem That Generics Solve 総称体が解決する問題

Here’s a standard, nongeneric function called swapTwoInts(_:_:), which swaps two Int values: ここに、通常の、非総称体のswapTwoInts(_:_:)と呼ばれる関数があります、それは、2つのInt値を交換します:

  1. func swapTwoInts(_ a: inout Int, _ b: inout Int) {
  2. let temporaryA = a
  3. a = b
  4. b = temporaryA
  5. }

This function makes use of in-out parameters to swap the values of a and b, as described in In-Out Parameters. この関数は、値abを交換するためにin-outパラメータの利用を行います、In-Outパラメータで記述されるように。

The swapTwoInts(_:_:) function swaps the original value of b into a, and the original value of a into b. You can call this function to swap the values in two Int variables: swapTwoInts(_:_:)関数は、bの元々の値をaの中へ、そしてaの元々の値をbの中へと交換します、そして、最初の値のにb。あなたは、2つのInt変数の値を交換するためにこの関数を呼ぶことができます:

  1. var someInt = 3
  2. var anotherInt = 107
  3. swapTwoInts(&someInt, &anotherInt)
  4. print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
  5. // Prints "someInt is now 107, and anotherInt is now 3"(「someIntは今は107、anotherIntは今は3です」を出力します)

The swapTwoInts(_:_:) function is useful, but it can only be used with Int values. If you want to swap two String values, or two Double values, you have to write more functions, such as the swapTwoStrings(_:_:) and swapTwoDoubles(_:_:) functions shown below: swapTwoInts(_:_:)関数は役に立ちます、しかし、それはInt値で使われることができるだけです。あなたが2つのString値、または2つのDoubleの値を交換したいならば、あなたはより多くの関数を書かなければなりません、例えば以下で示されるswapTwoStrings(_:_:)swapTwoDoubles(_:_:)関数のように:

  1. func swapTwoStrings(_ a: inout String, _ b: inout String) {
  2. let temporaryA = a
  3. a = b
  4. b = temporaryA
  5. }
  6. func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
  7. let temporaryA = a
  8. a = b
  9. b = temporaryA
  10. }

You may have noticed that the bodies of the swapTwoInts(_:_:), swapTwoStrings(_:_:), and swapTwoDoubles(_:_:) functions are identical. The only difference is the type of the values that they accept (Int, String, and Double). あなたは、swapTwoInts(_:_:)swapTwoStrings(_:_:)、そしてswapTwoDoubles(_:_:)関数の本文が同一であると気がついたかもしれません。唯一の違いは、それらが受け入れる値の型(IntString、そしてDouble)です。

It’s more useful, and considerably more flexible, to write a single function that swaps two values of any type. Generic code enables you to write such a function. (A generic version of these functions is defined below.) さらに役に立ち、そしてよりずっと柔軟であるのは、あらゆる型の2つの値を交換できるただ1つの関数を書くことです。総称体コードは、あなたにこのような関数を書くことを可能にします。(これらの関数の総称体版は、下で定義されます)。

Note 注意

In all three functions, the types of a and b must be the same. If a and b aren’t of the same type, it isn’t possible to swap their values. Swift is a type-safe language, and doesn’t allow (for example) a variable of type String and a variable of type Double to swap values with each other. Attempting to do so results in a compile-time error. 3つの関数すべてにおいて、abの型は同じでなければなりません。abが同じ型でないならば、それらの値を交換することは可能ではありません。スウィフトは型安全な言語です、それで(例えば)型Stringの変数と型Doubleの変数にお互いに値を交換させることをしません。そうしようとすることは、それでコンパイル時エラーという結果となります。

Generic Functions 総称体関数

Generic functions can work with any type. Here’s a generic version of the swapTwoInts(_:_:) function from above, called swapTwoValues(_:_:): 総称体関数は、どんな型でも扱うことができます。ここに、上記のswapTwoInts(_:_:)関数の総称体版があります、それはswapTwoValues(_:_:)と呼ばれます:

  1. func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
  2. let temporaryA = a
  3. a = b
  4. b = temporaryA
  5. }

The body of the swapTwoValues(_:_:) function is identical to the body of the swapTwoInts(_:_:) function. However, the first line of swapTwoValues(_:_:) is slightly different from swapTwoInts(_:_:). Here’s how the first lines compare: swapTwoValues(_:_:)関数の本文は、swapTwoInts(_:_:)関数の本文と同一です。しかし、swapTwoValues(_:_:)の最初の行は、わずかにswapTwoInts(_:_:)と異なります。最初の行がどのくらい似ているかが、ここにあります:

  1. func swapTwoInts(_ a: inout Int, _ b: inout Int)
  2. func swapTwoValues<T>(_ a: inout T, _ b: inout T)

The generic version of the function uses a placeholder type name (called T, in this case) instead of an actual type name (such as Int, String, or Double). The placeholder type name doesn’t say anything about what T must be, but it does say that both a and b must be of the same type T, whatever T represents. The actual type to use in place of T is determined each time the swapTwoValues(_:_:) function is called. この関数の総称体版は、プレースホルダ型名(この場合、Tと呼ばれるもの)を実際の型名(例えばIntString、またはDouble)の代わりに使用します。プレースホルダ型名はTが何でなければならないかについて何も言いません、しかし、abの両方ともが同じ型Tでなければならないと述べますTが表わすものが何であれ。Tの代わりに実際に使われる型は、swapTwoValues(_:_:)関数が呼ばれるたびに決定されます。

The other difference between a generic function and a nongeneric function is that the generic function’s name (swapTwoValues(_:_:)) is followed by the placeholder type name (T) inside angle brackets (<T>). The brackets tell Swift that T is a placeholder type name within the swapTwoValues(_:_:) function definition. Because T is a placeholder, Swift doesn’t look for an actual type called T. 総称体関数と非総称体関数の間の他の違いは、総称体関数の名前(swapTwoValues(_:_:))は、後ろにプレースホルダ型名(T)が山形括弧内部(<T>)で続くということです。この括弧は、TswapTwoValues(_:_:)関数定義内のプレースホルダ型名であるとスウィフトに教えます。Tがプレースホルダであるので、スウィフトはTと呼ばれる実際の型を捜しません。

The swapTwoValues(_:_:) function can now be called in the same way as swapTwoInts, except that it can be passed two values of any type, as long as both of those values are of the same type as each other. Each time swapTwoValues(_:_:) is called, the type to use for T is inferred from the types of values passed to the function. swapTwoValues(_:_:)関数は現在swapTwoIntsと同じやり方で呼ばれることができます、しかしそれがあらゆる型の2つの値を渡されることが、それらの値の両方が互いに同じ型である限り可能であるのを除きます。swapTwoValues(_:_:)が呼ばれるたびに、Tのために使われる型は関数に渡される値の型から推論されます。

In the two examples below, T is inferred to be Int and String respectively: 下の2つの例で、TはそれぞれIntStringであると推測されます:

  1. var someInt = 3
  2. var anotherInt = 107
  3. swapTwoValues(&someInt, &anotherInt)
  4. // someInt is now 107, and anotherInt is now 3(someIntは今は107、anotherIntは今は3です)
  5. var someString = "hello"
  6. var anotherString = "world"
  7. swapTwoValues(&someString, &anotherString)
  8. // someString is now "world", and anotherString is now "hello"(someStringは今は「world」、anotherStringは今は「hello」です)

Note 注意

The swapTwoValues(_:_:) function defined above is inspired by a generic function called swap, which is part of the Swift standard library, and is automatically made available for you to use in your apps. If you need the behavior of the swapTwoValues(_:_:) function in your own code, you can use Swift’s existing swap(_:_:) function rather than providing your own implementation. 上で定義されるswapTwoValues(_:_:)関数はswapと呼ばれる総称体関数に着想を得たものです、それは、スウィフト標準ライブラリの一部であって、あなたのアプリにおいて自動的にあなたが使うことが可能にされます。あなたがあなた自身のコードにおいてswapTwoValues(_:_:)関数の挙動を必要とするならば、あなたはあなた自身の実施を提供するのではなくスウィフトの既存のswap(_:_:)関数を使用することができます。

Type Parameters 型パラメータ

In the swapTwoValues(_:_:) example above, the placeholder type T is an example of a type parameter. Type parameters specify and name a placeholder type, and are written immediately after the function’s name, between a pair of matching angle brackets (such as <T>). 上のswapTwoValues(_:_:)例で、プレースホルダ型T型パラメータの一例です。型パラメータは、プレースホルダ型を指定して命名します、そして関数の名前の直後に一対の山形括弧の間で書かれます(例えば<T>)。

Once you specify a type parameter, you can use it to define the type of a function’s parameters (such as the a and b parameters of the swapTwoValues(_:_:) function), or as the function’s return type, or as a type annotation within the body of the function. In each case, the type parameter is replaced with an actual type whenever the function is called. (In the swapTwoValues(_:_:) example above, T was replaced with Int the first time the function was called, and was replaced with String the second time it was called.) 一旦あなたが型パラメータを指定するならば、あなたはそれを、関数のパラメータの型を定義するために(例えば、 swapTwoValues(_:_:)関数のabパラメータのように)、または関数の戻り型として、あるいは関数の本文内の型注釈として使用することができます。それぞれの場合において、型パラメータは、その関数が呼ばれるときはいつでも実際の型と取り替えられます。(上のswapTwoValues(_:_:)の例では、Tは関数が呼ばれた最初の時にIntと取り替えられて、それが呼ばれた2番目の時にStringと取り替えられました)。

You can provide more than one type parameter by writing multiple type parameter names within the angle brackets, separated by commas. あなたは、山形括弧内に複数の型パラメータ名をコンマで区切って書くことによって、複数の型パラメータを提供することができます。

Naming Type Parameters 型パラメータに名をつける

In most cases, type parameters have descriptive names, such as Key and Value in Dictionary<Key, Value> and Element in Array<Element>, which tells the reader about the relationship between the type parameter and the generic type or function it’s used in. However, when there isn’t a meaningful relationship between them, it’s traditional to name them using single letters such as T, U, and V, such as T in the swapTwoValues(_:_:) function above. ほとんどの場合には、型パラメータは描写的な名前を持ちます、たとえばDictionary<Key, Value>におけるKeyValueおよびArray<Element>におけるElementなど、それは読み手に型パラメータとそれがその中で使われる総称体型や関数との関係について語ります。しかしながら、意味がある関係がそれらの間に無かった時、TU、そしてVなどの一文字を使ってそれらに名前をつけるのが伝統的です、例えば上のswapTwoValues(_:_:)関数におけるTのように。

Note 注意

Always give type parameters upper camel case names (such as T and MyTypeParameter) to indicate that they’re a placeholder for a type, not a value. それらが、値ではなく、のためのプレースホルダであることを示すために、型パラメータに常にアッパーキャメルケース名(例えばTMyTypeParameterなど)を与えてください。

Generic Types 総称体型

In addition to generic functions, Swift enables you to define your own generic types. These are custom classes, structures, and enumerations that can work with any type, in a similar way to Array and Dictionary. 総称体関数に加えて、スウィフトはあなたに独自の総称体型を定義することを可能にします。これらは、ArrayDictionaryに類似した方法で、あらゆる型で扱うことができる特注のクラス、構造体、そして列挙があります。

This section shows you how to write a generic collection type called Stack. A stack is an ordered set of values, similar to an array, but with a more restricted set of operations than Swift’s Array type. An array allows new items to be inserted and removed at any location in the array. A stack, however, allows new items to be appended only to the end of the collection (known as pushing a new value on to the stack). Similarly, a stack allows items to be removed only from the end of the collection (known as popping a value off the stack). この節は、あなたにStackと呼ばれる総称体コレクション型を書く方法を示します。スタックは、順序付けられたいくつかの値の集合であり、配列に似ています、しかしスウィフトのArray型より制限された操作具合を持つものです。配列は、新しい項目を差し込まれたり取り外除かれることがその配列のどんな場所においても許されます。スタックは、しかし、新しい項目をコレクション終わりにのみ追加されることが許されます(新しい値をスタックにプッシュするとして知られます)。同じように、スタックは項目をコレクションの終わりからだけ取り除かれることが許されます(値をスタックからポップするとして知られます)。

Note 注意

The concept of a stack is used by the UINavigationController class to model the view controllers in its navigation hierarchy. You call the UINavigationController class pushViewController(_:animated:) method to add (or push) a view controller on to the navigation stack, and its popViewControllerAnimated(_:) method to remove (or pop) a view controller from the navigation stack. A stack is a useful collection model whenever you need a strict “last in, first out” approach to managing a collection. スタックの概念は、UINavigationControllerクラスで使用されて、そのナビゲーション階層においてビュー・コントローラをモデル化します。あなたはUINavigationControllerクラスのpushViewController(_:animated:)メソッドをナビゲーション・スタックにビュー・コントローラを加える(またはプッシュする)ために、そしてそれのpopViewControllerAnimated(_:)メソッドをナビゲーション・スタックからビュー・コントローラを取り除くために呼びます。スタックは、厳格に「最後に入れたものが、最初に取り出される」取り組みをコレクションを管理するために必要とするときはいつでも、役に立つコレクション・モデルです。

The illustration below shows the push and pop behavior for a stack: 下のイラストは、あるスタックのプッシュおよびポップ挙動を示します:

../_images/stackPushPop_2x.png
  1. There are currently three values on the stack. 現在は3つの値がこのスタックにはあります。
  2. A fourth value is pushed onto the top of the stack. 第4の値がスタックのてっぺんに押し込まれ(プッシュされ)ます。
  3. The stack now holds four values, with the most recent one at the top. スタックは現在は4つの値を持ちます、最も最近のものは一番上にあります。
  4. The top item in the stack is popped. スタックでの一番上の項目がポンと取り出され(ポップされ)ます。
  5. After popping a value, the stack once again holds three values. 値をポップした後では、スタックは再び3つの値を持ちます。

Here’s how to write a nongeneric version of a stack, in this case for a stack of Int values: スタックの非総称体版を書く方法がここにあります、これはInt値のスタックの場合です:

  1. struct IntStack {
  2. var items: [Int] = []
  3. mutating func push(_ item: Int) {
  4. items.append(item)
  5. }
  6. mutating func pop() -> Int {
  7. return items.removeLast()
  8. }
  9. }

This structure uses an Array property called items to store the values in the stack. Stack provides two methods, push and pop, to push and pop values on and off the stack. These methods are marked as mutating, because they need to modify (or mutate) the structure’s items array. この構造体は、itemsと呼ばれるArrayプロパティを使って値をスタックに格納します。Stackは2つのメソッド、pushpopを提供します、それでスタック上に値を押し込んだり飛び出させたりします。これらのメソッドはmutatingとして印されます、なぜなら、それらが構造体のitems配列を修正する(または変化させる)必要があるためです。

The IntStack type shown above can only be used with Int values, however. It would be much more useful to define a generic Stack structure, that can manage a stack of any type of value. しかし、上で示されるIntStack型は、Int値で使われることができるだけです。それをもっと役に立つようにするには、総称体 Stack構造体を定義することです、それはあらゆる型の値のスタックを管理することができるものです。

Here’s a generic version of the same code: 同じコードの総称体版は、ここにあります:

  1. struct Stack<Element> {
  2. var items: [Element] = []
  3. mutating func push(_ item: Element) {
  4. items.append(item)
  5. }
  6. mutating func pop() -> Element {
  7. return items.removeLast()
  8. }
  9. }

Note how the generic version of Stack is essentially the same as the nongeneric version, but with a type parameter called Element instead of an actual type of Int. This type parameter is written within a pair of angle brackets (<Element>) immediately after the structure’s name. Stackの総称体版が、本質的にどれほど非総称体版と同じものであるかに注意してください、しかしElementと呼ばれる型パラメータを実際の型Intの代わりに持つことは除きます。この型パラメータは、構造体の名前の直後に一対の山形括弧の内部で(<Element>)書かれます。

Element defines a placeholder name for a type to be provided later. This future type can be referred to as Element anywhere within the structure’s definition. In this case, Element is used as a placeholder in three places: Elementは、プレースホルダ名を、後で提供されることになるある型に対して定義します。この将来の型は、構造体の定義の範囲内のどこででも「Element」として参照されることができます。この場合、Elementはプレースホルダとして3つの場所で使われます:

  • To create a property called items, which is initialized with an empty array of values of type Element itemsと呼ばれるプロパティをつくる所で、それは、型Elementの値が入る空の配列で初期化されます
  • To specify that the push(_:) method has a single parameter called item, which must be of type Element push(_:)メソッドが1つのパラメータ、itemと呼ばれるものを持つことを指定する所で、それは、型Elementでなければなりません
  • To specify that the value returned by the pop() method will be a value of type Element pop()メソッドによって返される値が型Elementの値であることを示す所で

Because it’s a generic type, Stack can be used to create a stack of any valid type in Swift, in a similar manner to Array and Dictionary. それが総称体型であるので、Stackは、ArrayDictionaryに類似したやり方で、スウィフトにおけるあらゆる有効な型のスタックを作るために使われることができます。

You create a new Stack instance by writing the type to be stored in the stack within angle brackets. For example, to create a new stack of strings, you write Stack<String>(): あなたは、新しいStackインスタンスを、角括弧の内側にそのスタックの中に格納される型を書くことによって作成します。例えば、新しく文字列のスタックを作成するために、あなたはStack<String>()を書きます:

  1. var stackOfStrings = Stack<String>()
  2. stackOfStrings.push("uno")
  3. stackOfStrings.push("dos")
  4. stackOfStrings.push("tres")
  5. stackOfStrings.push("cuatro")
  6. // the stack now contains 4 strings(スタックは、現在4つの文字列を含みます)

Here’s how stackOfStrings looks after pushing these four values on to the stack: これらの4つの値をそのスタックにプッシュした後でstackOfStringsがどのように見えるかは、ここにあります:

../_images/stackPushedFourStrings_2x.png

Popping a value from the stack removes and returns the top value, "cuatro": このスタックから値をボップすることは、一番上の値、"cuatro"を削除して、返します:

  1. let fromTheTop = stackOfStrings.pop()
  2. // fromTheTop is equal to "cuatro", and the stack now contains 3 strings(fromTheTopは「cuatro」と等しいです、そしてスタックは現在は3つの文字列を含みます)

Here’s how the stack looks after popping its top value: スタックがその一番上の値をポップした後にどう見えるかは、ここにあります:

../_images/stackPoppedOneString_2x.png

Extending a Generic Type 総称体型を拡張する

When you extend a generic type, you don’t provide a type parameter list as part of the extension’s definition. Instead, the type parameter list from the original type definition is available within the body of the extension, and the original type parameter names are used to refer to the type parameters from the original definition. あなたがある総称体型を拡張する時、あなたは型パラメーターリストを拡張の定義の一部として提供しません。そうしなくても、元々の型定義からの型パラメーターリストは、その拡張の本文内で利用可能です、そして元々の型パラメーター名は、元々の定義からの型パラメーターを参照するために使われます。

The following example extends the generic Stack type to add a read-only computed property called topItem, which returns the top item on the stack without popping it from the stack: 以下の例は総称体Stack型を拡張して、topItemと呼ばれる読み出し専用の計算プロパティを加えます、それは、スタックの一番上の項目をスタックからそれをポップすることなく返します:

  1. extension Stack {
  2. var topItem: Element? {
  3. return items.isEmpty ? nil : items[items.count - 1]
  4. }
  5. }

The topItem property returns an optional value of type Element. If the stack is empty, topItem returns nil; if the stack isn’t empty, topItem returns the final item in the items array. topItemプロパティは型Elementのオプショナルの値を返します。スタックが空ならば、topItemnilを返します;スタックが空でないならば、topItemitems配列の最後の項目を返します。

Note that this extension doesn’t define a type parameter list. Instead, the Stack type’s existing type parameter name, Element, is used within the extension to indicate the optional type of the topItem computed property. この拡張は型パラメーターリストを定義しないことに注意してください。そうしなくても、Stack型の既存の型パラメーター名、Elementは、拡張の内部でtopItem計算プロパティの元々の型を指し示すために使われることができます。

The topItem computed property can now be used with any Stack instance to access and query its top item without removing it. topItem計算プロパティは、今やあらゆるStackインスタンスで、それの一番上の項目にそれを取り除くことなくアクセスおよび問い合わせるために使われることができます。

  1. if let topItem = stackOfStrings.topItem {
  2. print("The top item on the stack is \(topItem).")
  3. }
  4. // Prints "The top item on the stack is tres."(「このスタックの一番上の項目はtresです」を出力します)

Extensions of a generic type can also include requirements that instances of the extended type must satisfy in order to gain the new functionality, as discussed in Extensions with a Generic Where Clause below. ある総称体型のそれぞれの拡張はまた、拡張された型のインスタンスが新しい機能性を獲得する手段として満たさなければならない要件を含むことができます、下の総称体where節を持つ拡張で議論されるように。

Type Constraints 型制約

The swapTwoValues(_:_:) function and the Stack type can work with any type. However, it’s sometimes useful to enforce certain type constraints on the types that can be used with generic functions and generic types. Type constraints specify that a type parameter must inherit from a specific class, or conform to a particular protocol or protocol composition. swapTwoValues(_:_:)関数とStack型は、どんな型でも扱うことができます。しかし、総称体関数と総称体型で使われることができる型に、特定の型制約を強制することは、時々役に立ちます。型制約は、型パラメータが特定のクラスから継承しなければならない、もしくはある特定のプロトコルまたはプロトコル合成に準拠しなければならないことを指定します。

For example, Swift’s Dictionary type places a limitation on the types that can be used as keys for a dictionary. As described in Dictionaries, the type of a dictionary’s keys must be hashable. That is, it must provide a way to make itself uniquely representable. Dictionary needs its keys to be hashable so that it can check whether it already contains a value for a particular key. Without this requirement, Dictionary couldn’t tell whether it should insert or replace a value for a particular key, nor would it be able to find a value for a given key that’s already in the dictionary. 例えば、スウィフトのDictionary型は、辞書のキーとして使われることができる型に制限を置きます。辞書で記述されるように、辞書のキーの型は、ハッシュ化できなければなりません。すなわち、それはそれ自身を特有に表わすことを可能にする方法を提供しなければなりません。Dictionaryは、それが特定のキーのためにすでに値を含むかどうか確認できるように、そのキーにハッシュ化できることを必要とします。この要件なしでは、Dictionaryはそれが特定のキーのために値を差し込んだり取り替えたりするべきかどうか伝えることができませんし、それはすでに辞書の中にある指定されたキーに対する値を見つけることもできません。

This requirement is enforced by a type constraint on the key type for Dictionary, which specifies that the key type must conform to the Hashable protocol, a special protocol defined in the Swift standard library. All of Swift’s basic types (such as String, Int, Double, and Bool) are hashable by default. For information about making your own custom types conform to the Hashable protocol, see Conforming to the Hashable Protocol. この要件は、Dictionaryのためのキー型に関する型制約によって強制されます、それは、キー型がスウィフト標準ライブラリで定義される特別なプロトコル、Hashableプロトコルに準拠しなければならないことを示します。スウィフトの基本の型(例えばStringIntDouble、そしてBool)の全ては、初期状態でハッシュ化されます。あなた独自のあつらえの型をHashableプロトコルに準拠させることについての情報として、Hashableプロトコルに準拠するを見てください。

You can define your own type constraints when creating custom generic types, and these constraints provide much of the power of generic programming. Abstract concepts like Hashable characterize types in terms of their conceptual characteristics, rather than their concrete type. あなたは、独自の型制約をあつらえの総称体型を作成する時に定義することができます、そして、それらの制約は総称体プログラミングの力の多くを提供します。Hashableのような抽象的な概念それらは、それらの概念上の特徴の観点から型を特徴づけます、その具象型そのものではなく。

Type Constraint Syntax 型制約構文

You write type constraints by placing a single class or protocol constraint after a type parameter’s name, separated by a colon, as part of the type parameter list. The basic syntax for type constraints on a generic function is shown below (although the syntax is the same for generic types): あなたは、型パラメーターリストの一部として、型パラメータの名前の後にコロンで区切って1つのクラスまたはプロトコル制約を置くことによって、型制約を書きます。総称体関数に関する型制約のための基本の構文は、下で示されます(とはいえ構文は総称体型と同じものです):

  1. func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
  2. // function body goes here(関数本文が、ここにきます)
  3. }

The hypothetical function above has two type parameters. The first type parameter, T, has a type constraint that requires T to be a subclass of SomeClass. The second type parameter, U, has a type constraint that requires U to conform to the protocol SomeProtocol. 上の仮定の関数は、2つの型パラメータを持ちます。最初の型パラメータTは、TSomeClassのサブクラスであることを要求する型制約を持ちます。2番目の型パラメータUは、UにプロトコルSomeProtocolに準拠することを要求する型制約を持ちます。

Type Constraints in Action 型制約の動作

Here’s a nongeneric function called findIndex(ofString:in:), which is given a String value to find and an array of String values within which to find it. The findIndex(ofString:in:) function returns an optional Int value, which will be the index of the first matching string in the array if it’s found, or nil if the string can’t be found: ここにfindIndex(ofString:in:)と呼ばれる非総称体関数があります、それは、見つけるString値と、そこにおいてそれを捜すString値からなる配列を与えられます。findIndex(ofString:in:)関数は、オプショナルのInt値を返します、それは、それが見つけられるならば配列での最初の合致している文字列のインデックスです、または文字列が見つけられることができないならばnilです:

  1. func findIndex(ofString valueToFind: String, in array: [String]) -> Int? {
  2. for (index, value) in array.enumerated() {
  3. if value == valueToFind {
  4. return index
  5. }
  6. }
  7. return nil
  8. }

The findIndex(ofString:in:) function can be used to find a string value in an array of strings: findIndex(ofString:in:)関数は、文字列の配列の中をある文字列値がないか捜すために使われることができます:

  1. let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
  2. if let foundIndex = findIndex(ofString: "llama", in: strings) {
  3. print("The index of llama is \(foundIndex)")
  4. }
  5. // Prints "The index of llama is 2"(「ラマのインデックスは、2です」を出力します)

The principle of finding the index of a value in an array isn’t useful only for strings, however. You can write the same functionality as a generic function by replacing any mention of strings with values of some type T instead. しかし、配列の中の値のインデックスを見つける原理は、文字列のためにだけ役立つわけではありません。あなたは同じ機能性を総称体関数として書くことが、何であれ文字列への言及部分をその代わりにある何らかの型Tの値で置き換えることで行えます。

Here’s how you might expect a generic version of findIndex(ofString:in:), called findIndex(of:in:), to be written. Note that the return type of this function is still Int?, because the function returns an optional index number, not an optional value from the array. Be warned, though—this function doesn’t compile, for reasons explained after the example: あなたが予想するfindIndex(ofString:in:)の総称体版、findIndex(of:in:)と呼ばれるものが書かれる方法はここにあります。この関数の戻り型が以前としてInt?であるという点に注意してください、なぜなら、この関数がオプショナルのインデックス番号(配列からのオプショナルの値でない)を返すからです。注意するように、とは言うものの ― この関数はコンパイルしません、この例の後に説明される理由のために:

  1. func findIndex<T>(of valueToFind: T, in array:[T]) -> Int? {
  2. for (index, value) in array.enumerated() {
  3. if value == valueToFind {
  4. return index
  5. }
  6. }
  7. return nil
  8. }

This function doesn’t compile as written above. The problem lies with the equality check, “if value == valueToFind”. Not every type in Swift can be compared with the equal to operator (==). If you create your own class or structure to represent a complex data model, for example, then the meaning of “equal to” for that class or structure isn’t something that Swift can guess for you. Because of this, it isn’t possible to guarantee that this code will work for every possible type T, and an appropriate error is reported when you try to compile the code. この関数は、上記のように書かれるとしてもコンパイルしません。問題は、同等性検査if value == valueToFindに横たわります。スウィフトの中のすべての型が、同等演算子(==)で比較されることができるというわけでありません。あなたが例えば独自のクラスまたは構造体を作成してある複合データモデルを表すならば、そのときそのクラスまたは構造体のための「同等」の意味することはスウィフトがあなたのために推測することができる何かではありません。このため、このコードがすべての可能な型Tのために機能することを保証することは可能ではありません、それであなたがこのコードをコンパイルしようとする場合は該当するエラーが報告されます。

All is not lost, however. The Swift standard library defines a protocol called Equatable, which requires any conforming type to implement the equal to operator (==) and the not equal to operator (!=) to compare any two values of that type. All of Swift’s standard types automatically support the Equatable protocol. しかし、道がないわけではありません。スウィフト標準ライブラリは、Equatableと呼ばれるプロトコルを定義します、それは、それに準拠している全ての型に対してその型のあらゆる2つの値を比較するために同等演算子(==)と不等演算子(!=)を実装することを要求します。スウィフトの標準の型の全ては、自動的にEquatableプロトコルをサポートします。

Any type that’s Equatable can be used safely with the findIndex(of:in:) function, because it’s guaranteed to support the equal to operator. To express this fact, you write a type constraint of Equatable as part of the type parameter’s definition when you define the function: Equatableであるどんな型でもfindIndex(of:in:)関数で問題なく使われることができます、なぜなら、それが同等演算子をサポートすると保証されるからです。この事実を表すために、あなたはEquatableの型制約を型パラメータの定義の一部として、あなたが関数を定義する時に書きます:

  1. func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
  2. for (index, value) in array.enumerated() {
  3. if value == valueToFind {
  4. return index
  5. }
  6. }
  7. return nil
  8. }

The single type parameter for findIndex(of:in:) is written as T: Equatable, which means “any type T that conforms to the Equatable protocol.” findIndex(of:in:)のただ1つの型パラメータは、T: Equatableとして書かれます、それは、「何らかの型TEquatableプロトコルに準拠するもの」を意味します。

The findIndex(of:in:) function now compiles successfully and can be used with any type that’s Equatable, such as Double or String: findIndex(of:in:)関数は、今やうまくコンパイルして、Equatableであるどんな型とでも使われることができます、例えばDoubleStringなど:

  1. let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25])
  2. // doubleIndex is an optional Int with no value, because 9.3 isn't in the array(9.3がこの配列の中にはないので、doubleIndexは値のないオプショナルのIntです)
  3. let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"])
  4. // stringIndex is an optional Int containing a value of 2(stringIndexは、オプショナルのIntで値2を含んでいます)

Associated Types 関連型

When defining a protocol, it’s sometimes useful to declare one or more associated types as part of the protocol’s definition. An associated type gives a placeholder name to a type that’s used as part of the protocol. The actual type to use for that associated type isn’t specified until the protocol is adopted. Associated types are specified with the associatedtype keyword. プロトコルを定義するとき、時々役に立つのは、プロトコルの定義の一部として1つ以上の関連型を宣言することです。関連型は、プロトコルの一部として使われる型にプレースホルダ名を与えます。その関連型のために使われる実際の型は、プロトコルが採用されるまでは指定されません。関連型は、associatedtypeキーワードで指定されます。

Associated Types in Action 関連型の動作

Here’s an example of a protocol called Container, which declares an associated type called Item: Containerと呼ばれるプロトコルの例がここにあります、それはItemと呼ばれる関連型を宣言します:

  1. protocol Container {
  2. associatedtype Item
  3. mutating func append(_ item: Item)
  4. var count: Int { get }
  5. subscript(i: Int) -> Item { get }
  6. }

The Container protocol defines three required capabilities that any container must provide: Containerプロトコルは、あらゆるコンテナ(容れ物)が提供しなければならない3つの必須の能力を定義します:

  • It must be possible to add a new item to the container with an append(_:) method. 新しい項目をコンテナに加えることがappend(_:)メソッドで可能でなければなりません。
  • It must be possible to access a count of the items in the container through a count property that returns an Int value. コンテナの中の項目の総数にアクセスすることがInt値を返すcountプロパティを通して可能でなければなりません。
  • It must be possible to retrieve each item in the container with a subscript that takes an Int index value. コンテナの中の各項目を取り出すことがIntインデックス値をとる添え字で可能でなければなりません。

This protocol doesn’t specify how the items in the container should be stored or what type they’re allowed to be. The protocol only specifies the three bits of functionality that any type must provide in order to be considered a Container. A conforming type can provide additional functionality, as long as it satisfies these three requirements. このプロトコルは、コンテナの中の項目が格納されなければならない方法やそれらが許される型が何であるかを指定しません。プロトコルは、どんな型でもContainerとみなされるためには提供しなければならない小さな3つの機能性を指定するだけです。それに準拠している型は、それがこれらの3つの要件を満たす限り、追加の機能性を提供することができます。

Any type that conforms to the Container protocol must be able to specify the type of values it stores. Specifically, it must ensure that only items of the right type are added to the container, and it must be clear about the type of the items returned by its subscript. Containerプロトコルに準拠するあらゆる型は、それが格納する値の型を指定することができなければなりません。具体的には、それは正しい型の項目だけがコンテナに加えられることを確実にしなければなりません、そして、それはそれの添え字によって返される項目の型についてはっきりわかっていなければなりません。

To define these requirements, the Container protocol needs a way to refer to the type of the elements that a container will hold, without knowing what that type is for a specific container. The Container protocol needs to specify that any value passed to the append(_:) method must have the same type as the container’s element type, and that the value returned by the container’s subscript will be of the same type as the container’s element type. これらの要件を定義するために、Containerプロトコルは、あるコンテナが保持することになる要素の型を参照する方法を必要とします、その型がどんなコンテナのためのものか知ることなしにです。Containerプロトコルは、append(_:)メソッドに渡されるあらゆる値がそのコンテナの要素の型と同じ型を持たなければならないこと、そしてコンテナの添え字によって返される値がコンテナの要素型と同じ型のものになることを指定する必要があります。

To achieve this, the Container protocol declares an associated type called Item, written as associatedtype Item. The protocol doesn’t define what Item is—that information is left for any conforming type to provide. Nonetheless, the Item alias provides a way to refer to the type of the items in a Container, and to define a type for use with the append(_:) method and subscript, to ensure that the expected behavior of any Container is enforced. これを達成するために、ContainerプロトコルはItemと呼ばれる関連型を宣言します、それはassociatedtype Itemのように書かれます。このプロトコルは、Itemが何であるかを定義しません ― その情報は、何であれそれに準拠する型が提供するようにそのままにされます。それでもなお、Itemエイリアスは、Containerの中の項目の型に言及するための、そしてappend(_:)メソッドと添え字で使うための型を定義するための、ひとつの方法を提供します、それによってあらゆるContainerが期待される挙動を強制されることを確実にします。

Here’s a version of the nongeneric IntStack type from Generic Types above, adapted to conform to the Container protocol: ここに、上の総称体型からの非総称体IntStack型の改作、Containerプロトコルに準拠するために適応させたものがあります:

  1. struct IntStack: Container {
  2. // original IntStack implementation(元々のIntStack実施)
  3. var items: [Int] = []
  4. mutating func push(_ item: Int) {
  5. items.append(item)
  6. }
  7. mutating func pop() -> Int {
  8. return items.removeLast()
  9. }
  10. // conformance to the Container protocol(Containerプロトコルに準拠)
  11. typealias Item = Int
  12. mutating func append(_ item: Int) {
  13. self.push(item)
  14. }
  15. var count: Int {
  16. return items.count
  17. }
  18. subscript(i: Int) -> Int {
  19. return items[i]
  20. }
  21. }

The IntStack type implements all three of the Container protocol’s requirements, and in each case wraps part of the IntStack type’s existing functionality to satisfy these requirements. IntStack型は、Containerプロトコルの要件の3つすべてを実装します、そしてそれぞれの場合において、これらの要件を満たすためにIntStack型がもつ既存の機能性の一部をラップしています(内部で利用して外側を包む)。

Moreover, IntStack specifies that for this implementation of Container, the appropriate Item to use is a type of Int. The definition of typealias Item = Int turns the abstract type of Item into a concrete type of Int for this implementation of the Container protocol. さらに、IntStackは、Containerのこの実施のために、適切なItemとして使用するのはInt型であることを示します。定義typealias Item = Intは、抽象型Itemを具象型Intへと、Containerプロトコルのこの実装のために転向します。

Thanks to Swift’s type inference, you don’t actually need to declare a concrete Item of Int as part of the definition of IntStack. Because IntStack conforms to all of the requirements of the Container protocol, Swift can infer the appropriate Item to use, simply by looking at the type of the append(_:) method’s item parameter and the return type of the subscript. Indeed, if you delete the typealias Item = Int line from the code above, everything still works, because it’s clear what type should be used for Item. スウィフトの型推論のおかげで、あなたは実際にはIntである具体的なItemIntStackの定義の一部として宣言する必要がありません。IntStackContainerプロトコルの要件の全てに準拠するので、スウィフトは、単にappend(_:)メソッドのitemパラメータの型、そして、添え字の戻り型を見ることによって、使用するのに適切なitemを推論することができます。本当に、あなたが上のコードから行typealias Item = Intを削除するならば、すべては依然として働きます、なぜなら、どんな型がItemのために使われなければならないかは明白であるからです。

You can also make the generic Stack type conform to the Container protocol: あなたは、また、総称体Stack型をContainerプロトコルに準拠させることができます:

  1. struct Stack<Element>: Container {
  2. // original Stack<Element> implementation(元々のStack<Element>実装)
  3. var items: [Element] = []
  4. mutating func push(_ item: Element) {
  5. items.append(item)
  6. }
  7. mutating func pop() -> Element {
  8. return items.removeLast()
  9. }
  10. // conformance to the Container protocol(Containerプロトコルに準拠)
  11. mutating func append(_ item: Element) {
  12. self.push(item)
  13. }
  14. var count: Int {
  15. return items.count
  16. }
  17. subscript(i: Int) -> Element {
  18. return items[i]
  19. }
  20. }

This time, the type parameter Element is used as the type of the append(_:) method’s item parameter and the return type of the subscript. Swift can therefore infer that Element is the appropriate type to use as the Item for this particular container. 今度は、型パラメータElementが、append(_:)メソッドのitemパラメータの型および添え字の戻り型として使われます。スウィフトは、したがってElementが、この特定のコンテナのためのItemとして使うのに適当な型であると推測することができます。

Extending an Existing Type to Specify an Associated Type 既存の型を拡張して関連型を指定する

You can extend an existing type to add conformance to a protocol, as described in Adding Protocol Conformance with an Extension. This includes a protocol with an associated type. あなたは、拡張を使ってプロトコル準拠を加えるで記述されるように、既存の型を拡張することでプロトコルへの準拠を加えることができます。これは、関連型を使うプロトコルを含みます。

Swift’s Array type already provides an append(_:) method, a count property, and a subscript with an Int index to retrieve its elements. These three capabilities match the requirements of the Container protocol. This means that you can extend Array to conform to the Container protocol simply by declaring that Array adopts the protocol. You do this with an empty extension, as described in Declaring Protocol Adoption with an Extension: スウィフトのArray型は、すでにappend(_:)メソッド、countプロパティ、そしてその要素を取り出すためにIntインデックスを使う添え字を提供します。これらの3つの能力は、Containerプロトコルの要件に合致します。これは、あなたがArrayを拡張してContainerプロトコルに準拠することが、Arrayがそのプロトコルを採用すると宣言することによって可能であることを意味します。拡張を使ってプロトコル採用を宣言するで記述されるように、あなたは空の拡張でこれを行います

  1. extension Array: Container {}

Array’s existing append(_:) method and subscript enable Swift to infer the appropriate type to use for Item, just as for the generic Stack type above. After defining this extension, you can use any Array as a Container. 配列の既存のappend(_:)メソッドと添え字は、スウィフトに、ちょうど上の総称体Stack型と同じように、Itemに使うのに適当な型を推論するのを可能にします。この拡張を定義した後に、あなたはどんなArrayでもContainerとして使うことができます。

Adding Constraints to an Associated Type 関連型に制約を加える

You can add type constraints to an associated type in a protocol to require that conforming types satisfy those constraints. For example, the following code defines a version of Container that requires the items in the container to be equatable. あなたは、型制約を関連型へとプロトコルの中で加えることで、準拠する型がそれら制約を満たすことを要求できます。例えば、以下のコードはContainerのあるバージョンを定義します、それはコンテナの中の項目に同等評価可能であることを要求するものです。

  1. protocol Container {
  2. associatedtype Item: Equatable
  3. mutating func append(_ item: Item)
  4. var count: Int { get }
  5. subscript(i: Int) -> Item { get }
  6. }

To conform to this version of Container, the container’s Item type has to conform to the Equatable protocol. このバージョンのContainerに準拠するには、コンテナのもつItem型はEquatableプロトコルに準拠しなければなりません。

Using a Protocol in Its Associated Type’s Constraints あるプロトコルをそれの関連型のもつ制約において使用する

A protocol can appear as part of its own requirements. For example, here’s a protocol that refines the Container protocol, adding the requirement of a suffix(_:) method. The suffix(_:) method returns a given number of elements from the end of the container, storing them in an instance of the Suffix type. あるプロトコルは、それ自身の要件の一部として現れることができます。例えば、ここにContainerプロトコルを改良したプロトコルがあり、suffix(_:)メソッドという要件を追加しています。suffix(_:)メソッドは、コンテナの終わりから指定の数の要素を、それらをSuffix型のインスタンスの中に格納して、返します。

  1. protocol SuffixableContainer: Container {
  2. associatedtype Suffix: SuffixableContainer where Suffix.Item == Item
  3. func suffix(_ size: Int) -> Suffix
  4. }

In this protocol, Suffix is an associated type, like the Item type in the Container example above. Suffix has two constraints: It must conform to the SuffixableContainer protocol (the protocol currently being defined), and its Item type must be the same as the container’s Item type. The constraint on Item is a generic where clause, which is discussed in Associated Types with a Generic Where Clause below. このプロトコルにおいて、Suffixは関連型です、上のContainer例でのItem型のように。Suffixは、2つの制約を持ちます:それはSuffixableContainerプロトコル(そのプロトコルはいま定義されるところです)に準拠しなければなりません、そしてそれのItem型はコンテナのもつItem型と同じでなければなりません。Itemでの制約は総称体whereです、それは下のwhere節を持つ関連型において議論されます。

Here’s an extension of the Stack type from Generic Types above that adds conformance to the SuffixableContainer protocol: ここに、上のGeneric TypesからのStack型の拡張があります、それはSuffixableContainerプロトコルへの準拠を加えます:

  1. extension Stack: SuffixableContainer {
  2. func suffix(_ size: Int) -> Stack {
  3. var result = Stack()
  4. for index in (count-size)..<count {
  5. result.append(self[index])
  6. }
  7. return result
  8. }
  9. // Inferred that Suffix is Stack.(SuffixはStackであると推論される。)
  10. }
  11. var stackOfInts = Stack<Int>()
  12. stackOfInts.append(10)
  13. stackOfInts.append(20)
  14. stackOfInts.append(30)
  15. let suffix = stackOfInts.suffix(2)
  16. // suffix contains 20 and 30(suffix は 20 と 30を含む)

In the example above, the Suffix associated type for Stack is also Stack, so the suffix operation on Stack returns another Stack. Alternatively, a type that conforms to SuffixableContainer can have a Suffix type that’s different from itself—meaning the suffix operation can return a different type. For example, here’s an extension to the nongeneric IntStack type that adds SuffixableContainer conformance, using Stack<Int> as its suffix type instead of IntStack: 上の例において、StackのためのSuffix関連型もまたStackです、それでStack上のsuffix演算は別のStackを返します。あるいはまた、SuffixableContainerに準拠する型は、それ自身とは異なるSuffix型を持つことができます—suffix演算は異なる型を返すことができることになります。例えば、ここに非総称体IntStack型に対する拡張があります、それはSuffixableContainer準拠を、Stack<Int>をそれのsuffix型としてIntStackの代わりに使って追加します:

  1. extension IntStack: SuffixableContainer {
  2. func suffix(_ size: Int) -> Stack<Int> {
  3. var result = Stack<Int>()
  4. for index in (count-size)..<count {
  5. result.append(self[index])
  6. }
  7. return result
  8. }
  9. // Inferred that Suffix is Stack<Int>.(Suffix は Stack<Int>であると推論される。)
  10. }

Generic Where Clauses 総称体where節

Type constraints, as described in Type Constraints, enable you to define requirements on the type parameters associated with a generic function, subscript, or type. 型制約は、「型制約」で記述されるように、総称体の関数、添え字、または型と関連した型パラメータに要件を定義することをあなたに可能にします。

It can also be useful to define requirements for associated types. You do this by defining a generic where clause. A generic where clause enables you to require that an associated type must conform to a certain protocol, or that certain type parameters and associated types must be the same. A generic where clause starts with the where keyword, followed by constraints for associated types or equality relationships between types and associated types. You write a generic where clause right before the opening curly brace of a type or function’s body. 関連型のために要件を定義することは、また同様に役に立ちます。あなたはこれを総称体where節を定義する事によって行います。総称体where節は、ある関連型が特定のプロトコルに準拠しなければならないこと、または特定の型パラメータおよび関連型が同じでなければならないことをあなたが要求できるようにします。総称体where節は、whereキーワードで始まり、関連型に対する制約がいくつか、または型と関連型の間の同等関係性がいくつか続きます。あなたは、総称体where節を、型や関数のもつ本文の開き波括弧のまさに前に記述します。

The example below defines a generic function called allItemsMatch, which checks to see if two Container instances contain the same items in the same order. The function returns a Boolean value of true if all items match and a value of false if they don’t. 下の例はallItemsMatchと呼ばれる総称体関数を定義します、それは、2つのContainerインスタンスが同じ順序で同じ項目を含むかどうか見るために調べます。この関数は全ての項目が合致するならばブール値のtrueを、それらがそうしないならばfalseの値を返します。

The two containers to be checked don’t have to be the same type of container (although they can be), but they do have to hold the same type of items. This requirement is expressed through a combination of type constraints and a generic where clause: 調べられる2つのコンテナは、同じ型のコンテナである必要はありません(とは言えそうでもよい)、しかしそれらは同じ型の項目を持たなければなりません。この要件は、型制約と総称体where節の組合せによって表されます:

  1. func allItemsMatch<C1: Container, C2: Container>
  2. (_ someContainer: C1, _ anotherContainer: C2) -> Bool
  3. where C1.Item == C2.Item, C1.Item: Equatable {
  4. // Check that both containers contain the same number of items.(両方のコンテナが同じ数の項目を含むことを確認する。)
  5. if someContainer.count != anotherContainer.count {
  6. return false
  7. }
  8. // Check each pair of items to see if they're equivalent.(各項目の対をそれらが等しいかどうか見るため調べる。)
  9. for i in 0..<someContainer.count {
  10. if someContainer[i] != anotherContainer[i] {
  11. return false
  12. }
  13. }
  14. // All items match, so return true.(全ての項目が合致、なのでtrueを返す。)
  15. return true
  16. }

This function takes two arguments called someContainer and anotherContainer. The someContainer argument is of type C1, and the anotherContainer argument is of type C2. Both C1 and C2 are type parameters for two container types to be determined when the function is called. この関数は、someContaineranotherContainerと呼ばれる2つの引数をとります。someContainer引数は型C1です、そしてanotherContainer引数は型C2です。C1C2の両方は、2つのコンテナ型のための型パラメータで、関数が呼ばれるときに決定されます。

The following requirements are placed on the function’s two type parameters: 以下の要件は、この関数の持つ2つの型パラメータ上に置かれます:

  • C1 must conform to the Container protocol (written as C1: Container). C1は、Containerプロトコルに準拠しなければなりません(C1: Containerのように書かれます)。
  • C2 must also conform to the Container protocol (written as C2: Container). C2もまた、Containerプロトコルに準拠しなければなりません(C2: Containerのように書かれます)。
  • The Item for C1 must be the same as the Item for C2 (written as C1.Item == C2.Item). C1のためのItemは、C2のためのItemと同じものでなければなりません(C1.Item == C2.Itemのように書かれます)。
  • The Item for C1 must conform to the Equatable protocol (written as C1.Item: Equatable). C1のためのItemは、Equatableプロトコルに準拠しなければなりません(C1.Item: Equatableのように書かれます)。

The first and second requirements are defined in the function’s type parameter list, and the third and fourth requirements are defined in the function’s generic where clause. 最初と2番目の要件は関数のもつ型パラメータリストにおいて定義されます、そして3番目と4番目の要件は関数のもつ総称体where節において定義されます。

These requirements mean: これらの要件が意味するのは:

  • someContainer is a container of type C1. someContainerは、型C1のコンテナです。
  • anotherContainer is a container of type C2. anotherContainerは、型C2のコンテナです。
  • someContainer and anotherContainer contain the same type of items. someContaineranotherContainerは、同じ型の項目を含みます。
  • The items in someContainer can be checked with the not equal operator (!=) to see if they’re different from each other. someContainerの中の項目は、それらがお互いと異なるかどうか見るために不等演算子(!=)を使って確認されることができます。

The third and fourth requirements combine to mean that the items in anotherContainer can also be checked with the != operator, because they’re exactly the same type as the items in someContainer. 3番目と4番目の要件は組み合わされて、anotherContainerの中の項目が!=演算子を使って確認されることが同様に可能なことを意味します、なぜなら、それらはsomeContainerの中の項目と同じ正確に型であるからです。

These requirements enable the allItemsMatch(_:_:) function to compare the two containers, even if they’re of a different container type. これらの要件は、allItemsMatch(_:_:)関数に2つのコンテナを比較するのを可能にします、たとえそれらが異なるコンテナ型であるとしてもです。

The allItemsMatch(_:_:) function starts by checking that both containers contain the same number of items. If they contain a different number of items, there’s no way that they can match, and the function returns false. allItemsMatch(_:_:)関数は、両方のコンテナが同じ数の項目を含むことを確認することによって始まります。それらが異なる数の項目を含むならば、それらが合致することができる術はありません、そして関数はfalseを返します。

After making this check, the function iterates over all of the items in someContainer with a for-in loop and the half-open range operator (..<). For each item, the function checks whether the item from someContainer isn’t equal to the corresponding item in anotherContainer. If the two items aren’t equal, then the two containers don’t match, and the function returns false. この確認の後、関数はsomeContainerの項目の全てに渡ってfor-inループと半開範囲演算子(..<)を使って繰り返します。各項目のために、関数はsomeContainerからの項目がanotherContainerでの対応する項目と同等でないかどうか確認します。2つの項目が等しくないならば、2つのコンテナは合致しません、そして関数はfalseを返します。

If the loop finishes without finding a mismatch, the two containers match, and the function returns true. ループが一致しない組合せを見つけることなく終わるならば、2つのコンテナは合致します、そして関数はtrueを返します。

Here’s how the allItemsMatch(_:_:) function looks in action: 動作中のallItemsMatch(_:_:)関数がどのように見えるかが、ここにあります:

  1. var stackOfStrings = Stack<String>()
  2. stackOfStrings.push("uno")
  3. stackOfStrings.push("dos")
  4. stackOfStrings.push("tres")
  5. var arrayOfStrings = ["uno", "dos", "tres"]
  6. if allItemsMatch(stackOfStrings, arrayOfStrings) {
  7. print("All items match.")
  8. } else {
  9. print("Not all items match.")
  10. }
  11. // Prints "All items match."(「全ての項目が一致する」を出力します)

The example above creates a Stack instance to store String values, and pushes three strings onto the stack. The example also creates an Array instance initialized with an array literal containing the same three strings as the stack. Even though the stack and the array are of a different type, they both conform to the Container protocol, and both contain the same type of values. You can therefore call the allItemsMatch(_:_:) function with these two containers as its arguments. In the example above, the allItemsMatch(_:_:) function correctly reports that all of the items in the two containers match. 上の例は、StackインスタンスをつくってString値を格納します、そしてスタック上へ3つの文字列をプッシュします。この例はまた、このスタックと同じ3つの文字列を含む配列リテラルで初期化されるArrayインスタンスをつくります。たとえスタックと配列が異なる型であるとしても、それらは両方ともContainerプロトコルに準拠して、両方とも同じ型の値を含みます。あなたは、したがって、allItemsMatch(_:_:)関数をその引数としてこれらの2つのコンテナを使って呼ぶことができます。上の例で、allItemsMatch(_:_:)関数は、2つのコンテナの中の項目の全てが一致すると正しく報告します。

Extensions with a Generic Where Clause 総称体where節を持つ拡張

You can also use a generic where clause as part of an extension. The example below extends the generic Stack structure from the previous examples to add an isTop(_:) method. あなたまた、総称体where節を拡張の一部として使うことができます。下の例は、以前の例の総称体Stack構造体を拡張して、isTop(_:)メソッドを加えます。

  1. extension Stack where Element: Equatable {
  2. func isTop(_ item: Element) -> Bool {
  3. guard let topItem = items.last else {
  4. return false
  5. }
  6. return topItem == item
  7. }
  8. }

This new isTop(_:) method first checks that the stack isn’t empty, and then compares the given item against the stack’s topmost item. If you tried to do this without a generic where clause, you would have a problem: The implementation of isTop(_:) uses the == operator, but the definition of Stack doesn’t require its items to be equatable, so using the == operator results in a compile-time error. Using a generic where clause lets you add a new requirement to the extension, so that the extension adds the isTop(_:) method only when the items in the stack are equatable. この新しいisTop(_:)メソッドは、まずスタックが空でないことを確認します、それから与えられた項目をスタックの持つ最も上の項目と比較します。あなたが総称体where節なしにこれをしようとするならば、あなたは問題を抱えることになるでしょう:isTop(_:)の実装は==演算子を使います、しかしStackの定義はそれの項目に同等評価可能であることを要求しません、それで==演算子の使用はコンパイル時エラーという結果になります。総称体where節を使うことは、あなたに新しい要件をその拡張に追加させます、それで拡張はisTop(_:)メソッドをスタックの中の項目が同等評価可能なものである時のみ加えます。

Here’s how the isTop(_:) method looks in action: 動作中のisTop(_:)メソッドがどのように見えるかが、ここにあります:

  1. if stackOfStrings.isTop("tres") {
  2. print("Top element is tres.")
  3. } else {
  4. print("Top element is something else.")
  5. }
  6. // Prints "Top element is tres."

If you try to call the isTop(_:) method on a stack whose elements aren’t equatable, you’ll get a compile-time error. あなたがisTop(_:)メソッドを、それの持つ要素が同等評価可能でないスタック上で呼び出そうとするならば、あなたはコンパイル時エラーを得るでしょう。

  1. struct NotEquatable { }
  2. var notEquatableStack = Stack<NotEquatable>()
  3. let notEquatableValue = NotEquatable()
  4. notEquatableStack.push(notEquatableValue)
  5. notEquatableStack.isTop(notEquatableValue) // Error

You can use a generic where clause with extensions to a protocol. The example below extends the Container protocol from the previous examples to add a startsWith(_:) method. あなたは、総称体where節をプロトコルに対する拡張で使うことができます。下の例は、以前の例のContainerプロトコルを拡張して、startsWith(_:)メソッドを追加します。

  1. extension Container where Item: Equatable {
  2. func startsWith(_ item: Item) -> Bool {
  3. return count >= 1 && self[0] == item
  4. }
  5. }

The startsWith(_:) method first makes sure that the container has at least one item, and then it checks whether the first item in the container matches the given item. This new startsWith(_:) method can be used with any type that conforms to the Container protocol, including the stacks and arrays used above, as long as the container’s items are equatable. startsWith(_:)メソッドはまず、コンテナが少なくとも1つの項目を持つことを確かめます、それからそれはそのコンテナの最初の項目が与えられた項目と合致するかどうか調べます。この新しいstartsWith(_:)メソッドはContainerプロトコルに準拠するあらゆる型で使われることができます、上で使われるスタックと配列を含めて、コンテナの持つ項目が同等評価可能である限りは。

  1. if [9, 9, 9].startsWith(42) {
  2. print("Starts with 42.")
  3. } else {
  4. print("Starts with something else.")
  5. }
  6. // Prints "Starts with something else."

The generic where clause in the example above requires Item to conform to a protocol, but you can also write a generic where clauses that require Item to be a specific type. For example: 上の例の総称体where節は、Itemに要求してあるプロトコルに準拠させます、しかしあなたはまたItemに特定の型であることを要求する総称体where節を書くことができます。例えば:

  1. extension Container where Item == Double {
  2. func average() -> Double {
  3. var sum = 0.0
  4. for index in 0..<count {
  5. sum += self[index]
  6. }
  7. return sum / Double(count)
  8. }
  9. }
  10. print([1260.0, 1200.0, 98.6, 37.0].average())
  11. // Prints "648.9"

This example adds an average() method to containers whose Item type is Double. It iterates over the items in the container to add them up, and divides by the container’s count to compute the average. It explicitly converts the count from Int to Double to be able to do floating-point division. この例は、average()メソッドを、Item型がDoubleであるコンテナに追加します。それは、コンテナの中の項目すべてにわたって繰り返していき、それらを合計します、そしてコンテナの総数で除算することで平均を計算します。それは、明示的に総数をIntからDoubleへ変換して、浮動小数点除算ができるようにします。

You can include multiple requirements in a generic where clause that’s part of an extension, just like you can for a generic where clause that you write elsewhere. Separate each requirement in the list with a comma. あなたは、複数の要件を拡張の一部であるひとつのwhere節の中に含めることができます、ちょうどあなたがどこか他で書く総称体where節に対してできるように。リストの中の各要件をコンマで区切ってください。

Contextual Where Clauses 文脈where節

You can write a generic where clause as part of a declaration that doesn’t have its own generic type constraints, when you’re already working in the context of generic types. For example, you can write a generic where clause on a subscript of a generic type or on a method in an extension to a generic type. The Container structure is generic, and the where clauses in the example below specify what type constraints have to be satisfied to make these new methods available on a container. あなたは総称体where節を、それ自身の総称体型制約を持たないある宣言の一部として書くことが、あなたが既に総称体型の文脈の中で作業している時は可能です。例えば、あなたは総称体where節をある総称体型の添え字上でまたはある総称体型への拡張の中のメソッド上で書くことができます。Container構造体は総称体です、そして下の例の中のwhere節は、どんな型制約がそれら新しいメソッドをあるコンテナ上で利用可能にするためには満たされなければならないかを指定します。

  1. extension Container {
  2. func average() -> Double where Item == Int {
  3. var sum = 0.0
  4. for index in 0..<count {
  5. sum += Double(self[index])
  6. }
  7. return sum / Double(count)
  8. }
  9. func endsWith(_ item: Item) -> Bool where Item: Equatable {
  10. return count >= 1 && self[count-1] == item
  11. }
  12. }
  13. let numbers = [1260, 1200, 98, 37]
  14. print(numbers.average())
  15. // Prints "648.75"(「648.75」を出力します)
  16. print(numbers.endsWith(37))
  17. // Prints "true"(「true」を出力します)

This example adds an average() method to Container when the items are integers, and it adds an endsWith(_:) method when the items are equatable. Both functions include a generic where clause that adds type constraints to the generic Item type parameter from the original declaration of Container. この例は、average()メソッドをContainerへとその項目が整数である場合は加えます、そしてそれはendsWith(_:)メソッドを項目が同等評価可能である場合は加えます。両方の関数は、ある総称体where節を含みます、それは型制約をContainerの元の宣言由来の総称体Item型パラメータに加えます。

If you want to write this code without using contextual where clauses, you write two extensions, one for each generic where clause. The example above and the example below have the same behavior. あなたがこのコードを文脈where節を使うことなく書きたいならば、あなたは2つの拡張を書きます、各where節のために1つ。上の例と下の例は同じ挙動を持ちます。

  1. extension Container where Item == Int {
  2. func average() -> Double {
  3. var sum = 0.0
  4. for index in 0..<count {
  5. sum += Double(self[index])
  6. }
  7. return sum / Double(count)
  8. }
  9. }
  10. extension Container where Item: Equatable {
  11. func endsWith(_ item: Item) -> Bool {
  12. return count >= 1 && self[count-1] == item
  13. }
  14. }

In the version of this example that uses contextual where clauses, the implementation of average() and endsWith(_:) are both in the same extension because each method’s generic where clause states the requirements that need to be satisfied to make that method available. Moving those requirements to the extensions’ generic where clauses makes the methods available in the same situations, but requires one extension per requirement. この例の文脈where節を使うバージョンでは、average()endsWith(_:)の実装は両方とも同じ拡張の中にあります、なぜなら各メソッドのもつ総称体where節それらが、そのメソッドを利用可能にするのに満足させる必要がある要件を述べるからです。それらの要件を拡張のもつ総称体where節に移動することは、メソッドそれらを同じ状況で利用可能にします、しかし要件ごとに1つの拡張を要します。

Associated Types with a Generic Where Clause 総称体where節を持つ関連型

You can include a generic where clause on an associated type. For example, suppose you want to make a version of Container that includes an iterator, like what the Sequence protocol uses in the standard library. Here’s how you write that: あなたは、総称体where節を関連型に関して含めることができます。例えば、あなたがContainerのあるバージョンを作りたいと仮定してください、それはあるイテレータ、標準ライブラリで使われているSequenceプロトコルのようなものを含みます。あなたがそれをどう書くかここにあります:

  1. protocol Container {
  2. associatedtype Item
  3. mutating func append(_ item: Item)
  4. var count: Int { get }
  5. subscript(i: Int) -> Item { get }
  6. associatedtype Iterator: IteratorProtocol where Iterator.Element == Item
  7. func makeIterator() -> Iterator
  8. }

The generic where clause on Iterator requires that the iterator must traverse over elements of the same item type as the container’s items, regardless of the iterator’s type. The makeIterator() function provides access to a container’s iterator. この総称体where節がIterator上で要求するのは、そのイテレータがコンテナのもつ要素と同じ項目型の要素に対して見ていくことです、そのイテレータの持つ型に関係なく。makeIterator()関数は、コンテナの持つイテレータに対するアクセスを提供します。

For a protocol that inherits from another protocol, you add a constraint to an inherited associated type by including the generic where clause in the protocol declaration. For example, the following code declares a ComparableContainer protocol that requires Item to conform to Comparable: 別のプロトコルから継承するプロトコルに対して、あなたは継承された関連型への制約の追加を、総称体where節をそのプロトコル宣言の中で含めることによって行います。例えば、以下のコードはComparableContainerプロトコルを宣言します、それはItemComparableに準拠することを要求します:

  1. protocol ComparableContainer: Container where Item: Comparable { }

Generic Subscripts 総称体添え字

Subscripts can be generic, and they can include generic where clauses. You write the placeholder type name inside angle brackets after subscript, and you write a generic where clause right before the opening curly brace of the subscript’s body. For example: 添え字は総称体であることができます、そしてそれらは総称体where節を含むことができます。あなたは、プレースホルダ型名を山括弧の内部にsubscriptの後に書きます、そしてあなたは総称体where節を添え字本文の開き波括弧の直前に書きます。例えば:

  1. extension Container {
  2. subscript<Indices: Sequence>(indices: Indices) -> [Item]
  3. where Indices.Iterator.Element == Int {
  4. var result: [Item] = []
  5. for index in indices {
  6. result.append(self[index])
  7. }
  8. return result
  9. }
  10. }

This extension to the Container protocol adds a subscript that takes a sequence of indices and returns an array containing the items at each given index. This generic subscript is constrained as follows: このContainerプロトコルに対する拡張は、ある添え字を追加します、それはインデックスのシーケンスをとって、与えられたインデックスそれぞれでの項目を含んでいる配列を返します。この総称体添え字は、以下のように制約されます:

  • The generic parameter Indices in angle brackets has to be a type that conforms to the Sequence protocol from the standard library. 山括弧の中の総称体パラメータIndicesは、それは標準ライブラリからのSequenceプロトコルに準拠する型でなければなりません。
  • The subscript takes a single parameter, indices, which is an instance of that Indices type. この添え字は、ただ1つだけのパラメータ、indicesをとります、それはIndices型のインスタンスです。
  • The generic where clause requires that the iterator for the sequence must traverse over elements of type Int. This ensures that the indices in the sequence are the same type as the indices used for a container. この総称体where節が要求するのは、このシーケンスのためのイテレータが型Intの要素について見ていかなければなければならないことです。これは、このシーケンスのインデックスがコンテナに対して使われるインデックスと同じ型であるのを保証することになります。

Taken together, these constraints mean that the value passed for the indices parameter is a sequence of integers. 総合すると、これらの制約が意味するのは、indicesパラメータに対して渡される値は整数からなるシーケンスであるということです。

Protocols プロトコル

Opaque Types 不透明型