Protocols プロトコル

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol. あるプロトコル(規約)は、メソッド、プロパティ、そして他の要件からなるひとつの青写真を定義します、それは、ある特定の作業またはある機能性断片にふさわしくするものです。そのプロトコルは、それから、クラス、構造体、または列挙によって採用されることで、それらの要件の実際の実装を提供することができます。あるプロトコルの要件を満たす何らかの型は、そのプロトコルに準拠すると言われます。

In addition to specifying requirements that conforming types must implement, you can extend a protocol to implement some of these requirements or to implement additional functionality that conforming types can take advantage of. 準拠する型が実装しなければならない要件を指定することに加えて、あなたはあるプロトコルを拡張してそれらの要件のいくつかを実装したり、更なる機能性を実装したりできます、それらは、準拠する型それぞれで利用可能です。

Protocol Syntax プロトコル構文

You define protocols in a very similar way to classes, structures, and enumerations: あなたは、クラス、構造体、および列挙と非常に類似した方法で、プロトコルを定義します:

  1. protocol SomeProtocol {
  2. // protocol definition goes here(プロトコル定義が、ここにきます)
  3. }

Custom types state that they adopt a particular protocol by placing the protocol’s name after the type’s name, separated by a colon, as part of their definition. Multiple protocols can be listed, and are separated by commas: あつらえの型は、それが特定のプロトコルを採用することを、型の名前の後に、コロンで区切って、それらの定義の一部としてプロトコルの名前を置くことによって示します。複数のプロトコルが、コンマで区切られて、リストされることができます:

  1. struct SomeStructure: FirstProtocol, AnotherProtocol {
  2. // structure definition goes here(構造体定義が、ここにきます)
  3. }

If a class has a superclass, list the superclass name before any protocols it adopts, followed by a comma: あるクラスがスーパークラスを持つならば、それが採用するあらゆるプロトコルの前に、コンマに続けてスーパークラス名を列記してください:

  1. class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
  2. // class definition goes here(クラス定義が、ここにきます)
  3. }

Property Requirements プロパティ要件

A protocol can require any conforming type to provide an instance property or type property with a particular name and type. The protocol doesn’t specify whether the property should be a stored property or a computed property—it only specifies the required property name and type. The protocol also specifies whether each property must be gettable or gettable and settable. あるプロトコルは、あらゆる準拠型に、特定の名前と型をもつインスタンスプロパティまたは型プロパティを提供するように要求することができます。プロトコルは、そのプロパティが格納プロパティまたは計算プロパティでなければならないかどうかは指定しません ― それは、必要なプロパティ名と型を指定するだけです。プロトコルはまた、各プロパティが取得可能または取得可能かつまた設定可能でなければならないかどうか指定します。

If a protocol requires a property to be gettable and settable, that property requirement can’t be fulfilled by a constant stored property or a read-only computed property. If the protocol only requires a property to be gettable, the requirement can be satisfied by any kind of property, and it’s valid for the property to be also settable if this is useful for your own code. あるプロトコルがプロパティに取得可能かつまた設定可能であることを要求するならば、そのプロパティ要件は、定数格納プロパティまたは読み出し専用の計算プロパティによって満たされることができません。プロトコルがプロパティに取得可能であるのを要求するだけならば、その要件はどんなプロパティにでもよって満たされることができます、そして、同時にまた設定可能でもあることは、もしそれがあなた自身のコードに役立つ場合には、そのプロパティにとって有効です。

Property requirements are always declared as variable properties, prefixed with the var keyword. Gettable and settable properties are indicated by writing { get set } after their type declaration, and gettable properties are indicated by writing { get }. プロパティ要件は常に変数プロパティとして宣言されます、それでvarキーワードを前に置かれます。取得可能かつまた設定可能なプロパティは、それらの型宣言の後に{ get set }を書くことによって示されます、そして取得可能なプロパティは{ get }を書くことによって示されます。

  1. protocol SomeProtocol {
  2. var mustBeSettable: Int { get set }
  3. var doesNotNeedToBeSettable: Int { get }
  4. }

Always prefix type property requirements with the static keyword when you define them in a protocol. This rule pertains even though type property requirements can be prefixed with the class or static keyword when implemented by a class: あなたがあるプロトコルにおいてそれを定義するとき、常に、型プロパティ要件の前にstaticキーワードを置いてください。たとえ型プロパティ要件がクラスによって実装されるときclassまたはstaticキーワードを前に置かれるとしても、この規則は当てはまります:

  1. protocol AnotherProtocol {
  2. static var someTypeProperty: Int { get set }
  3. }

Here’s an example of a protocol with a single instance property requirement: ただ1つのインスタンスプロパティ要件を持つプロトコルの例が、ここにあります:

  1. protocol FullyNamed {
  2. var fullName: String { get }
  3. }

The FullyNamed protocol requires a conforming type to provide a fully qualified name. The protocol doesn’t specify anything else about the nature of the conforming type—it only specifies that the type must be able to provide a full name for itself. The protocol states that any FullyNamed type must have a gettable instance property called fullName, which is of type String. FullyNamedプロトコルは、完全修飾名を提供するある準拠型を要件とします。このプロトコルは、その準拠型の性質について何ら指定しません ― それはただその型がそれ自身のフルネームを提供できなければならないことだけを指定します。このプロトコルは、あらゆるFullyNamed型はfullNameと呼ばれる、String型である、取得可能なインスタンスプロパティを持たなければならないことを述べます。

Here’s an example of a simple structure that adopts and conforms to the FullyNamed protocol: FullyNamedプロトコルを採用して準拠する単純な構造体の例は、ここにあります:

  1. struct Person: FullyNamed {
  2. var fullName: String
  3. }
  4. let john = Person(fullName: "John Appleseed")
  5. // john.fullName is "John Appleseed"(john.fullNameは、「John Appleseed」です)

This example defines a structure called Person, which represents a specific named person. It states that it adopts the FullyNamed protocol as part of the first line of its definition. この例は、Personと呼ばれる構造体を定義します、それは、特定の名前の人物を表します。それは、その定義の最初の行の部分でそれがFullyNamedプロトコルを採用すると述べます。

Each instance of Person has a single stored property called fullName, which is of type String. This matches the single requirement of the FullyNamed protocol, and means that Person has correctly conformed to the protocol. (Swift reports an error at compile time if a protocol requirement isn’t fulfilled.) Personの各インスタンスは、fullNameと呼ばれる1つの格納プロパティを持ちます、それは、型Stringです。これは、FullyNamedプロトコルの唯一の要件に適合します、したがってそのPersonが正しくそのプロトコルに従ったことを意味します。(プロトコル要件が満たされないならば、スウィフトは実行時にエラーを報告します)。

Here’s a more complex class, which also adopts and conforms to the FullyNamed protocol: また、FullyNamedプロトコルを採用して準拠するさらに複雑なクラスが、ここにあります:

  1. class Starship: FullyNamed {
  2. var prefix: String?
  3. var name: String
  4. init(name: String, prefix: String? = nil) {
  5. self.name = name
  6. self.prefix = prefix
  7. }
  8. var fullName: String {
  9. return (prefix != nil ? prefix! + " " : "") + name
  10. }
  11. }
  12. var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
  13. // ncc1701.fullName is "USS Enterprise"(ncc1701.fullNameは、USSエンタープライズです)

This class implements the fullName property requirement as a computed read-only property for a starship. Each Starship class instance stores a mandatory name and an optional prefix. The fullName property uses the prefix value if it exists, and prepends it to the beginning of name to create a full name for the starship. このクラスは、fullNameプロパティ要件をある宇宙船のための読み出し専用の計算プロパティとして実装します。各Starshipクラスインスタンスは、義務的なnameそしてオプショナルのprefixを格納します。fullNameプロパティは、prefix値を、それが存在するならば使います、そしてそれをnameの始めに付けて、その宇宙船の完全な名前をつくります。

Method Requirements メソッド要件

Protocols can require specific instance methods and type methods to be implemented by conforming types. These methods are written as part of the protocol’s definition in exactly the same way as for normal instance and type methods, but without curly braces or a method body. Variadic parameters are allowed, subject to the same rules as for normal methods. Default values, however, can’t be specified for method parameters within a protocol’s definition. プロトコルは、準拠型によって特定のインスタンスメソッドと型メソッドが実装されるように要求することができます。これらのメソッドは、プロトコルの定義の一部として普通のインスタンスおよび型メソッドと正確に同じ方法で書かれます、しかし波括弧またはメソッド本文はありません。可変長パラメータは、許され、普通のメソッドと同じ規則の支配下にあります。省略時の値は、しかしながら、プロトコル定義の内部のメソッドパラメーターに対して指定されることはできません。

As with type property requirements, you always prefix type method requirements with the static keyword when they’re defined in a protocol. This is true even though type method requirements are prefixed with the class or static keyword when implemented by a class: 型プロパティ要件と同様に、あなたは常に型メソッド要件の前に、それらがプロトコルにおいて定義されるとき、staticキーワードを置きます。たとえ型メソッド要件がクラスによって実装されるときclassまたはstaticキーワードを前に置かれるとしても、これは当てはまります:

  1. protocol SomeProtocol {
  2. static func someTypeMethod()
  3. }

The following example defines a protocol with a single instance method requirement: 以下の例は、1つのインスタンスメソッド要件で、プロトコルを定義します:

  1. protocol RandomNumberGenerator {
  2. func random() -> Double
  3. }

This protocol, RandomNumberGenerator, requires any conforming type to have an instance method called random, which returns a Double value whenever it’s called. Although it’s not specified as part of the protocol, it’s assumed that this value will be a number from 0.0 up to (but not including) 1.0. このプロトコル、RandomNumberGeneratorは、あらゆる準拠型にrandomと呼ばれるインスタンスメソッドを持つことを要求します、それは、それが呼ばれた時はいつでもあるDouble値を返すものです。それはプロトコルの一部として指定されないけれども、この値は0.0から1.0まで(しかし含めてではない)のある数であるのを仮定されます。

The RandomNumberGenerator protocol doesn’t make any assumptions about how each random number will be generated—it simply requires the generator to provide a standard way to generate a new random number. RandomNumberGeneratorプロトコルは、乱数それぞれが生成される方法について、全く仮定しません ― それは単に生成器に新しい乱数を生み出す標準の方法を提供することを要求します。

Here’s an implementation of a class that adopts and conforms to the RandomNumberGenerator protocol. This class implements a pseudorandom number generator algorithm known as a linear congruential generator: RandomNumberGeneratorプロトコルを採用して準拠するクラスの実施が、ここにあります。このクラスは、線形合同法生成器として知られている擬似乱数生成器アルゴリズムを実装します:

  1. class LinearCongruentialGenerator: RandomNumberGenerator {
  2. var lastRandom = 42.0
  3. let m = 139968.0
  4. let a = 3877.0
  5. let c = 29573.0
  6. func random() -> Double {
  7. lastRandom = ((lastRandom * a + c)
  8. .truncatingRemainder(dividingBy:m))
  9. return lastRandom / m
  10. }
  11. }
  12. let generator = LinearCongruentialGenerator()
  13. print("Here's a random number: \(generator.random())")
  14. // Prints "Here's a random number: 0.3746499199817101"(「ここに任意の数: 0.3746499199817101があります」を出力します)
  15. print("And another one: \(generator.random())")
  16. // Prints "And another one: 0.729023776863283"(「さらにもう1つ:0.729023776863283」を出力します)

Mutating Method Requirements 変更メソッド要件

It’s sometimes necessary for a method to modify (or mutate) the instance it belongs to. For instance methods on value types (that is, structures and enumerations) you place the mutating keyword before a method’s func keyword to indicate that the method is allowed to modify the instance it belongs to and any properties of that instance. This process is described in Modifying Value Types from Within Instance Methods. メソッドがそれが属しているインスタンスを修正する(または変化させる)ことは、時々必要です。値型(すなわち、構造体と列挙)のインスタンスメソッドのために、あなたはmutatingキーワードをメソッドのfuncキーワードの前に置いて、メソッドがそれが属しているインスタンスおよびそのインスタンスのあらゆるプロパティを修正するのを許可されることを示します。この過程は、値型をインスタンスメソッド内から修正するで記述されます。

If you define a protocol instance method requirement that’s intended to mutate instances of any type that adopts the protocol, mark the method with the mutating keyword as part of the protocol’s definition. This enables structures and enumerations to adopt the protocol and satisfy that method requirement. あなたがそのプロトコルを採用するあらゆる型のインスタンスを変化させることを意図したインスタンスメソッド要件プロトコルを定義するならば、プロトコルの定義の一部としてそのメソッドにmutatingキーワードで印をつけてください。これは、構造体と列挙に、そのプロトコルを採用してメソッド要件を満たすのを可能にします。

Note 注意

If you mark a protocol instance method requirement as mutating, you don’t need to write the mutating keyword when writing an implementation of that method for a class. The mutating keyword is only used by structures and enumerations. あなたがインスタンスメソッド要件プロトコルにmutatingとして印するならば、あるクラスのためにそのメソッドの実装を書くとき、あなたはmutatingキーワードを書く必要がありません。mutatingキーワードは、構造体と列挙によって使われるだけです。

The example below defines a protocol called Togglable, which defines a single instance method requirement called toggle. As its name suggests, the toggle() method is intended to toggle or invert the state of any conforming type, typically by modifying a property of that type. 下の例は、Togglableと呼ばれるプロトコルを定義します、それは、toggleと呼ばれる1つのインスタンスメソッド要件を定義します。その名前が暗示するように、toggle()メソッドはあらゆる準拠型の状態を切り換えるか逆にすることを意図します、概してその型のプロパティの修正によって。

The toggle() method is marked with the mutating keyword as part of the Togglable protocol definition, to indicate that the method is expected to mutate the state of a conforming instance when it’s called: toggle()メソッドは、Togglableプロトコル定義の一部としてmutatingキーワードで印されます、それによってそのメソッドが、それが呼ばれるとき準拠インスタンスの状態を変化させることを予期されるようにします:

  1. protocol Togglable {
  2. mutating func toggle()
  3. }

If you implement the Togglable protocol for a structure or enumeration, that structure or enumeration can conform to the protocol by providing an implementation of the toggle() method that’s also marked as mutating. あなたがTogglableプロトコルをある構造体または列挙のために実装するならば、その構造体または列挙は、同様にmutatingとして印されるtoggle()メソッドの実施を提供することによって、このプロトコルに準拠できます。

The example below defines an enumeration called OnOffSwitch. This enumeration toggles between two states, indicated by the enumeration cases on and off. The enumeration’s toggle implementation is marked as mutating, to match the Togglable protocol’s requirements: 下の例は、OnOffSwitchと呼ばれる列挙を定義します。この列挙は、列挙のケース節onoffで示される、2つの状態の間で切替えをします。列挙のtoggle実装は、Togglableプロトコルの要件に適合するように、mutatingとして印されます:

  1. enum OnOffSwitch: Togglable {
  2. case off, on
  3. mutating func toggle() {
  4. switch self {
  5. case .off:
  6. self = .on
  7. case .on:
  8. self = .off
  9. }
  10. }
  11. }
  12. var lightSwitch = OnOffSwitch.off
  13. lightSwitch.toggle()
  14. // lightSwitch is now equal to .on(lightSwitchは、現在.onと等しいです)

Initializer Requirements イニシャライザ要件

Protocols can require specific initializers to be implemented by conforming types. You write these initializers as part of the protocol’s definition in exactly the same way as for normal initializers, but without curly braces or an initializer body: プロトコルは、準拠型によって特定のイニシャライザが実装されるように要求することができます。あなたは、これらのイニシャライザをプロトコル定義の一部として普通のイニシャライザと正確に同じ方法で書くことができます、しかし波括弧またはイニシャライザ本文はありません:

  1. protocol SomeProtocol {
  2. init(someParameter: Int)
  3. }

Class Implementations of Protocol Initializer Requirements イニシャライザ要件プロトコルのクラス実装

You can implement a protocol initializer requirement on a conforming class as either a designated initializer or a convenience initializer. In both cases, you must mark the initializer implementation with the required modifier: あなたは、イニシャライザ要件プロトコルを準拠クラス上で指定イニシャライザまたは便宜イニシャライザとして実装することができます。両方の場合で、あなたはそのイニシャライザ実装をrequired修飾子で印しなければなりません:

  1. class SomeClass: SomeProtocol {
  2. required init(someParameter: Int) {
  3. // initializer implementation goes here(イニシャライザ実装がここに来ます)
  4. }
  5. }

The use of the required modifier ensures that you provide an explicit or inherited implementation of the initializer requirement on all subclasses of the conforming class, such that they also conform to the protocol. required修飾子の使用は、あなたがある明確なもしくは継承されたイニシャライザ要件の実装を準拠クラスの全てのサブクラス上で、それらもまたそのプロトコルに準拠するように、提供することを確かなものにします。

For more information on required initializers, see Required Initializers. 必須イニシャライザに関する更なる情報として、必須イニシャライザを見てください。

Note 注意

You don’t need to mark protocol initializer implementations with the required modifier on classes that are marked with the final modifier, because final classes can’t subclassed. For more about the final modifier, see Preventing Overrides. あなたはfinal修飾子で印されるクラス上でプロトコルイニシャライザ実装をrequired修飾子で印する必要はありません、なぜなら、finalクラスはサブクラスを作られることができないからです。final修飾子に関する詳細は、オーバーライドを防ぐを見てください。

If a subclass overrides a designated initializer from a superclass, and also implements a matching initializer requirement from a protocol, mark the initializer implementation with both the required and override modifiers: あるサブクラスが、スーパークラスからの指定イニシャライザをオーバーライドして、またプロトコルからのイニシャライザ要件にも合致するものを実装するならば、そのイニシャライザ実装をrequiredoverrideの両方の修飾子を使って印してください:

  1. protocol SomeProtocol {
  2. init()
  3. }
  4. class SomeSuperClass {
  5. init() {
  6. // initializer implementation goes here(イニシャライザ実装がここに来ます)
  7. }
  8. }
  9. class SomeSubClass: SomeSuperClass, SomeProtocol {
  10. // "required" from SomeProtocol conformance; "override" from SomeSuperClass(SomeProtocol準拠からの「required」;SomeSuperClasからの「override」)
  11. required override init() {
  12. // initializer implementation goes here(イニシャライザ実装がここに来ます)
  13. }
  14. }

Failable Initializer Requirements 失敗できるイニシャライザ要件

Protocols can define failable initializer requirements for conforming types, as defined in Failable Initializers. プロトコルは、失敗できるイニシャライザで記述されるように、準拠している型に対して失敗できるイニシャライザ要件を定義することができます。

A failable initializer requirement can be satisfied by a failable or nonfailable initializer on a conforming type. A nonfailable initializer requirement can be satisfied by a nonfailable initializer or an implicitly unwrapped failable initializer. 失敗できるイニシャライザ要件は、準拠している型上の失敗できるもしくは失敗できないイニシャライザによって満たされることができます。失敗できないイニシャライザ要件は、失敗できないイニシャライザまたは暗黙的にアンラップされる失敗できるイニシャライザによって満たされることができます。

Protocols as Types 型としてのプロトコル

Protocols don’t actually implement any functionality themselves. Nonetheless, you can use protocols as a fully fledged types in your code. Using a protocol as a type is sometimes called an existential type, which comes from the phrase “there exists a type T such that T conforms to the protocol”. プロトコルは、実際に少しの機能性も実装しません。それにもかかわらず、あなたはプロトコルを完全に一人前の型としてあなたのコードにおいて使用できます。プロトコルを型として使うことは、ときどき存在型と呼ばれます、それは語句 “そこに型Tが存在する、そのようなTはそのプロトコルに準拠する” から来ています。

You can use a protocol in many places where other types are allowed, including: あなたは、プロトコルを、他の型が許可される多くの場所で使用できます、以下を含みます:

  • As a parameter type or return type in a function, method, or initializer 関数、メソッド、またはイニシャライザにおいてパラメータ型または戻り型として
  • As the type of a constant, variable, or property 定数、変数、またはプロパティの型として
  • As the type of items in an array, dictionary, or other container 配列、辞書、または他のコンテナ中の項目の型として

Note 注意

Because protocols are types, begin their names with a capital letter (such as FullyNamed and RandomNumberGenerator) to match the names of other types in Swift (such as Int, String, and Double). プロトコルが型であるので、それらの名前を大文字で開始してください(例えばFullyNamedRandomNumberGeneratorのように)、それによってスウィフトでの他の型の名前(例えばIntString、およびDouble)と釣り合いがとれます。

Here’s an example of a protocol used as a type: 型として使われるプロトコルの例は、ここにあります:

  1. class Dice {
  2. let sides: Int
  3. let generator: RandomNumberGenerator
  4. init(sides: Int, generator: RandomNumberGenerator) {
  5. self.sides = sides
  6. self.generator = generator
  7. }
  8. func roll() -> Int {
  9. return Int(generator.random() * Double(sides)) + 1
  10. }
  11. }

This example defines a new class called Dice, which represents an n-sided dice for use in a board game. Dice instances have an integer property called sides, which represents how many sides they have, and a property called generator, which provides a random number generator from which to create dice roll values. この例はDiceと呼ばれる新しいクラスを定義します、それは、ボードゲームで使うのためにn面のさいころを表します。Diceインスタンスは、それがどれくらいの面を持つのかを表すsidesと呼ばれる整数プロパティ、そしてそこからさいころを振った値を作成する乱数生成器を提供するgeneratorと呼ばれるプロパティを持ちます。

The generator property is of type RandomNumberGenerator. Therefore, you can set it to an instance of any type that adopts the RandomNumberGenerator protocol. Nothing else is required of the instance you assign to this property, except that the instance must adopt the RandomNumberGenerator protocol. Because its type is RandomNumberGenerator, code inside the Dice class can only interact with generator in ways that apply to all generators that conform to this protocol. That means it can’t use any methods or properties that are defined by the underlying type of the generator. However, you can downcast from a protocol type to an underlying type in the same way you can downcast from a superclass to a subclass, as discussed in Downcasting. generatorプロパティは、型RandomNumberGeneratorのものです。したがって、あなたはそれをRandomNumberGeneratorプロトコルを採用するあらゆる型のインスタンスに設定できます。そのインスタンスがRandomNumberGeneratorプロトコルを採用しなければならないことをのぞいては、あなたがこのプロパティに代入するところのインスタンスに必要とされるものは他に何もありません。それの型がRandomNumberGeneratorであることから、Diceクラスの内部のコードは、全ての生成子にこのプロトコルに準拠することを適用するという方法でgeneratorと相互作用できるだけです。それは意味するのは、それが生成子の基礎をなす型によって定義されるどんなメソッドまたはプロパティも使用できないということです。しかしながら、あなたはあるプロトコル型からある基礎をなす型へとダウンキャストすることが、あなたがスーパークラスからサブクラスへとダウンキャスト出来るのと同じ方法で可能です、ダウンキャストで記述されるように。

Dice also has an initializer, to set up its initial state. This initializer has a parameter called generator, which is also of type RandomNumberGenerator. You can pass a value of any conforming type in to this parameter when initializing a new Dice instance. Diceはまた、その最初の状態を設定するために、イニシャライザを持ちます。このイニシャライザは、generatorと呼ばれるパラメータを持ちます、それもまた、型RandomNumberGeneratorです。新しいDiceインスタンスを初期化するとき、あなたはどんな準拠型の値でもこのパラメータに渡すことができます。

Dice provides one instance method, roll, which returns an integer value between 1 and the number of sides on the dice. This method calls the generator’s random() method to create a new random number between 0.0 and 1.0, and uses this random number to create a dice roll value within the correct range. Because generator is known to adopt RandomNumberGenerator, it’s guaranteed to have a random() method to call. Diceは1つのインスタンスメソッド、rollを提供します、それは、1とさいころ上の面の数との間の整数値を返します。このメソッドは、0.01.0の間で新しい乱数をつくるgeneratorのrandom()メソッドを呼んで、この乱数を正しい範囲内でさいころを振った値をつくるために使います。generatorRandomNumberGeneratorを採用すると知られているので、それはrandom()メソッドを呼ぶことを保証されます。

Here’s how the Dice class can be used to create a six-sided dice with a LinearCongruentialGenerator instance as its random number generator: Diceクラスが、6面のさいころをつくるためにその乱数生成器としてLinearCongruentialGeneratorインスタンスをつかってどのように使われることができるかが、ここにあります:

  1. var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
  2. for _ in 1...5 {
  3. print("Random dice roll is \(d6.roll())")
  4. }
  5. // Random dice roll is 3(無作為にさいころを転がして、3です)
  6. // Random dice roll is 5(無作為にさいころを転がして、5です)
  7. // Random dice roll is 4(無作為にさいころを転がして、4です)
  8. // Random dice roll is 5(無作為にさいころを転がして、5です)
  9. // Random dice roll is 4(無作為にさいころを転がして、4です)

Delegation 委任

Delegation is a design pattern that enables a class or structure to hand off (or delegate) some of its responsibilities to an instance of another type. This design pattern is implemented by defining a protocol that encapsulates the delegated responsibilities, such that a conforming type (known as a delegate) is guaranteed to provide the functionality that has been delegated. Delegation can be used to respond to a particular action, or to retrieve data from an external source without needing to know the underlying type of that source. 委任は、クラスまたは構造体にそれのもつ責務の一部を別の型のインスタンスへと手渡す(または委任する)ことを可能にするデザイン・パターンです。このデザイン・パターンは、委任された責務をカプセル化するプロトコルを定義することによって実装されます、例えば、委任プロトコルに拠準する型が(代表、委任先として知られるものが)その委任されている機能性を提供する責任を負わされるといったこと。委任は、特定の動作に応答したり、外部ソースからそのソースの根底の型を知る必要なしにデータを取り出したりするのに使われることができます。

The example below defines two protocols for use with dice-based board games: 下の例は、さいころに基づく様々なボードゲームで使うために、2つのプロトコルを定義します:

  1. protocol DiceGame {
  2. var dice: Dice { get }
  3. func play()
  4. }
  5. protocol DiceGameDelegate: AnyObject {
  6. func gameDidStart(_ game: DiceGame)
  7. func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
  8. func gameDidEnd(_ game: DiceGame)
  9. }

The DiceGame protocol is a protocol that can be adopted by any game that involves dice. DiceGameプロトコルは、さいころが関わるどんなゲームによってでも採用されることができるプロトコルです。

The DiceGameDelegate protocol can be adopted to track the progress of a DiceGame. To prevent strong reference cycles, delegates are declared as weak references. For information about weak references, see Strong Reference Cycles Between Class Instances. Marking the protocol as class-only lets the SnakesAndLadders class later in this chapter declare that its delegate must use a weak reference. A class-only protocol is marked by its inheritance from AnyObject, as discussed in Class-Only Protocols. DiceGameDelegateプロトコルが採用されることで、DiceGameの進捗を追いかけることができます。強い参照循環を防ぐために、委任先は弱い参照として宣言されます。弱い参照についての詳細は、クラスインスタンス間の強い参照循環を見てください。プロトコルをクラス専用とすることは、SnakesAndLaddersクラスに後でこの章においてその委任先が弱い参照を使わなければならないことを宣言させます。クラス専用プロトコルは、AnyObjectからのそれの継承によって印されます、クラス専用プロトコルにおいて議論されるように。

Here’s a version of the Snakes and Ladders game originally introduced in Control Flow. This version is adapted to use a Dice instance for its dice-rolls; to adopt the DiceGame protocol; and to notify a DiceGameDelegate about its progress: 制御の流れで元々は紹介されるヘビとはしごゲームのひとつの改作が、ここにあります。この版は改変され、それにより、それのさいころ振りにDiceインスタンスを使用します;DiceGameプロトコルを採用します;そして、その進歩についてDiceGameDelegateに通知します:

  1. class SnakesAndLadders: DiceGame {
  2. let finalSquare = 25
  3. let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
  4. var square = 0
  5. var board: [Int]
  6. init() {
  7. board = Array(repeating: 0, count: finalSquare + 1)
  8. board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
  9. board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
  10. }
  11. weak var delegate: DiceGameDelegate?
  12. func play() {
  13. square = 0
  14. delegate?.gameDidStart(self)
  15. gameLoop: while square != finalSquare {
  16. let diceRoll = dice.roll()
  17. delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
  18. switch square + diceRoll {
  19. case finalSquare:
  20. break gameLoop
  21. case let newSquare where newSquare > finalSquare:
  22. continue gameLoop
  23. default:
  24. square += diceRoll
  25. square += board[square]
  26. }
  27. }
  28. delegate?.gameDidEnd(self)
  29. }
  30. }

For a description of the Snakes and Ladders gameplay, see Break. ヘビとはしごのゲームプレイの解説として、Breakを見てください。

This version of the game is wrapped up as a class called SnakesAndLadders, which adopts the DiceGame protocol. It provides a gettable dice property and a play() method in order to conform to the protocol. (The dice property is declared as a constant property because it doesn’t need to change after initialization, and the protocol only requires that it must be gettable.) ゲームのこの改作は、SnakesAndLaddersと呼ばれるクラスで包まれます、それは、DiceGameプロトコルを採用します。それは、プロトコルに従うために取得可能なdiceプロパティとplay()メソッドを提供します。(diceプロパティは定数プロパティとして宣言されます、なぜなら、それが初期化の後に変化する必要がなく、そして、プロトコルはそれが取得可能なことを必要とするだけであるからです)。

The Snakes and Ladders game board setup takes place within the class’s init() initializer. All game logic is moved into the protocol’s play method, which uses the protocol’s required dice property to provide its dice roll values. ヘビとはしごゲーム盤設定は、このクラスのinit()イニシャライザ内で行われます。全てのゲーム論理は、プロトコルのplayメソッドに引っ越します、それは、プロトコルの要求するdiceプロパティを使ってそれのさいころ振りの値を提供します。

Note that the delegate property is defined as an optional DiceGameDelegate, because a delegate isn’t required in order to play the game. Because it’s of an optional type, the delegate property is automatically set to an initial value of nil. Thereafter, the game instantiator has the option to set the property to a suitable delegate. Because the DiceGameDelegate protocol is class-only, you can declare the delegate to be weak to prevent reference cycles. delegateプロパティが、オプショナルDiceGameDelegateとして定義される点に注意してください、delegateがゲームをプレイするために必須でないからです。それがオプショナル型であるので、delegateプロパティは自動的に初期値のnilに設定されます。その後は、このゲームのイニシャライザは、このプロパティを適当な委任先に設定する選択肢を持ちます。DiceGameDelegateプロトコルがクラス専用であることから、あなたは委任先をweakであると宣言して参照循環を防ぐことができます。

DiceGameDelegate provides three methods for tracking the progress of a game. These three methods have been incorporated into the game logic within the play() method above, and are called when a new game starts, a new turn begins, or the game ends. DiceGameDelegateは、3つのメソッドをゲームの進捗を追うために提供します。これらの3つのメソッドは、上のplay()メソッド内のゲーム論理に組み込まれています、そして、新しいゲームが始まるとき、新しいターンを開始するとき、あるいはこのゲームが終わるとき、呼ばれます。

Because the delegate property is an optional DiceGameDelegate, the play() method uses optional chaining each time it calls a method on the delegate. If the delegate property is nil, these delegate calls fail gracefully and without error. If the delegate property is non-nil, the delegate methods are called, and are passed the SnakesAndLadders instance as a parameter. delegateプロパティがオプショナルDiceGameDelegateであるので、play()メソッドは、それが委任先でメソッドを呼ぶたびにオプショナル連鎖を使います。delegateプロパティがnilならば、これらの委任先呼び出しはエラーなしで美しく失敗します。delegateプロパティがnilでないならば、委任先のさまざまなメソッドが呼ばれます、そしてパラメータとしてSnakesAndLaddersインスタンスを渡されます。

This next example shows a class called DiceGameTracker, which adopts the DiceGameDelegate protocol: この次の例はDiceGameTrackerと呼ばれるクラスを示します、それは、DiceGameDelegateプロトコルを採用します:

  1. class DiceGameTracker: DiceGameDelegate {
  2. var numberOfTurns = 0
  3. func gameDidStart(_ game: DiceGame) {
  4. numberOfTurns = 0
  5. if game is SnakesAndLadders {
  6. print("Started a new game of Snakes and Ladders")
  7. }
  8. print("The game is using a \(game.dice.sides)-sided dice")
  9. }
  10. func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
  11. numberOfTurns += 1
  12. print("Rolled a \(diceRoll)")
  13. }
  14. func gameDidEnd(_ game: DiceGame) {
  15. print("The game lasted for \(numberOfTurns) turns")
  16. }
  17. }

DiceGameTracker implements all three methods required by DiceGameDelegate. It uses these methods to keep track of the number of turns a game has taken. It resets a numberOfTurns property to zero when the game starts, increments it each time a new turn begins, and prints out the total number of turns once the game has ended. DiceGameTrackerは、DiceGameDelegateによって要求される3つのメソッド全てを実装します。それは、あるゲームがとったターンの数の情報を得続けるためにこれらのメソッドを使用します。それは、ゲームが始まるときnumberOfTurnsプロパティをゼロに再設定します、新しいターンが開始するときそれぞれそれを増加させます、そしてひとたびゲームが終わってしまったならばターンの総数を出力します。

The implementation of gameDidStart(_:) shown above uses the game parameter to print some introductory information about the game that’s about to be played. The game parameter has a type of DiceGame, not SnakesAndLadders, and so gameDidStart(_:) can access and use only methods and properties that are implemented as part of the DiceGame protocol. However, the method is still able to use type casting to query the type of the underlying instance. In this example, it checks whether game is actually an instance of SnakesAndLadders behind the scenes, and prints an appropriate message if so. 上で示されるgameDidStart(_:)の実装は、gameパラメータを使って、プレイされようとしているゲームに関する若干の紹介の情報を出力します。gameパラメータは、型DiceGameを持ちます、SnakesAndLaddersではありません、なので、gameDidStart(_:)DiceGameプロトコルの一部として実施されるメソッドとプロパティだけにアクセスして使用することができます。しかし、このメソッドは依然として基盤インスタンスの型についてたずねるために型キャストを使うことができます。この例では、gameが実際に舞台裏でSnakesAndLaddersのインスタンスであるかどうか調べて、もしそうならば適切なメッセージを出力します。

The gameDidStart(_:) method also accesses the dice property of the passed game parameter. Because game is known to conform to the DiceGame protocol, it’s guaranteed to have a dice property, and so the gameDidStart(_:) method is able to access and print the dice’s sides property, regardless of what kind of game is being played. gameDidStart(_:)メソッドはまた、渡されたgameパラメータのdiceプロパティにアクセスします。gameDiceGameプロトコルに従うと知られているので、それはdiceプロパティを持つと保証されます、なので、gameDidStart(_:)メソッドは、どんな種類のゲームがプレイされているかに関係なく、diceのsidesプロパティにアクセスして出力することができます。

Here’s how DiceGameTracker looks in action: 動作中のDiceGameTrackerがどのように見えるかは、ここにあります:

  1. let tracker = DiceGameTracker()
  2. let game = SnakesAndLadders()
  3. game.delegate = tracker
  4. game.play()
  5. // Started a new game of Snakes and Ladders(ヘビとはしごの新しいゲームを始める)
  6. // The game is using a 6-sided dice(ゲームは、6面のさいころを使っています)
  7. // Rolled a 3(3を出した)
  8. // Rolled a 5(5を出した)
  9. // Rolled a 4(4を出した)
  10. // Rolled a 5(5を出した)
  11. // The game lasted for 4 turns(ゲームは、4回続きました)

Adding Protocol Conformance with an Extension 拡張を使ってプロトコル準拠を加える

You can extend an existing type to adopt and conform to a new protocol, even if you don’t have access to the source code for the existing type. Extensions can add new properties, methods, and subscripts to an existing type, and are therefore able to add any requirements that a protocol may demand. For more about extensions, see Extensions. あなたは、ある新しいプロトコルを採用して準拠することで既存の型を拡張することができます、たとえあなたが既存の型のソース・コードにアクセスをしないとしてもです。拡張は、新しいプロパティ、メソッド、そして添え字を既存の型に加えることができます、したがって、あるプロトコルが要求するであろうどんな要件でも加えることができます。拡張についてのより多くのために、拡張を見てください。

Note 注意

Existing instances of a type automatically adopt and conform to a protocol when that conformance is added to the instance’s type in an extension. ある型の既存のインスタンスそれらは、そのインスタンスの型に拡張の中で準拠が加えられるとき、そのプロトコルを自動的に採用して準拠します。

For example, this protocol, called TextRepresentable, can be implemented by any type that has a way to be represented as text. This might be a description of itself, or a text version of its current state: 例えば、このプロトコル、TextRepresentableと呼ばれるものは、テキストとして表わされる方法を持つどんな型によってでも実装されることができます。これは、それ自身の説明、またはテキスト版のそれの現在の状態であるかもしれません:

  1. protocol TextRepresentable {
  2. var textualDescription: String { get }
  3. }

The Dice class from above can be extended to adopt and conform to TextRepresentable: 上のDiceクラスは、拡張されることで、TextRepresentableを採用して準拠することができます:

  1. extension Dice: TextRepresentable {
  2. var textualDescription: String {
  3. return "A \(sides)-sided dice"
  4. }
  5. }

This extension adopts the new protocol in exactly the same way as if Dice had provided it in its original implementation. The protocol name is provided after the type name, separated by a colon, and an implementation of all requirements of the protocol is provided within the extension’s curly braces. この拡張は、まるでDiceがその最初の実装においてそれを提供したかのように、正確に同じふうに新しいプロトコルを採用します。プロトコル名は、型名の後にコロンで区切られて提供されます、そして、プロトコルの全ての要件の実装は、拡張の波括弧内で提供されます。

Any Dice instance can now be treated as TextRepresentable: どんなDiceインスタンスでも、今やTextRepresentableとして扱われることができます:

  1. let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
  2. print(d12.textualDescription)
  3. // Prints "A 12-sided dice"(「ひとつの12面さいころ」を出力します)

Similarly, the SnakesAndLadders game class can be extended to adopt and conform to the TextRepresentable protocol: 同じように、SnakesAndLaddersゲーム・クラスは、拡張されることで、TextRepresentableプロトコルを採用して準拠することができます:

  1. extension SnakesAndLadders: TextRepresentable {
  2. var textualDescription: String {
  3. return "A game of Snakes and Ladders with \(finalSquare) squares"
  4. }
  5. }
  6. print(game.textualDescription)
  7. // Prints "A game of Snakes and Ladders with 25 squares"(「25ますのヘビとはしごのゲーム」を出力します)

Conditionally Conforming to a Protocol あるプロトコルに条件付きで準拠する

A generic type may be able to satisfy the requirements of a protocol only under certain conditions, such as when the type’s generic parameter conforms to the protocol. You can make a generic type conditionally conform to a protocol by listing constraints when extending the type. Write these constraints after the name of the protocol you’re adopting by writing a generic where clause. For more about generic where clauses, see Generic Where Clauses. 総称体型は、あるプロトコルの要件を満たすことが一定の条件の下でのみ可能でしょう、例えばその型のもつ総称体パラメータがそのプロトコルに準拠する場合など。あなたは、ある総称体型を条件付きでプロトコルに準拠させることが、その型を拡張する時に制約を列記することによって可能です。それらの制約を、あなたが総称体where節を書くことによって採用しているプロトコルの名前の後に書いてください。総称体where節に関する詳細は、総称体where節を見てください。

The following extension makes Array instances conform to the TextRepresentable protocol whenever they store elements of a type that conforms to TextRepresentable. 以下の拡張は、ArrayインスタンスをTextRepresentableプロトコルに準拠させます、それがTextRepresentableに準拠する型の要素を格納する時は必ずです。

  1. extension Array: TextRepresentable where Element: TextRepresentable {
  2. var textualDescription: String {
  3. let itemsAsText = self.map { $0.textualDescription }
  4. return "[" + itemsAsText.joined(separator: ", ") + "]"
  5. }
  6. }
  7. let myDice = [d6, d12]
  8. print(myDice.textualDescription)
  9. // Prints "[A 6-sided dice, A 12-sided dice]"

Declaring Protocol Adoption with an Extension 拡張を使ってプロトコル採用を宣言する

If a type already conforms to all of the requirements of a protocol, but hasn’t yet stated that it adopts that protocol, you can make it adopt the protocol with an empty extension: ある型があるプロトコルの要件の全てにすでに準拠するが、それがそのプロトコルを採用するとまだ示していなかったならば、あなたは空の拡張を使ってそれがそのプロトコルを採用するようにできます:

  1. struct Hamster {
  2. var name: String
  3. var textualDescription: String {
  4. return "A hamster named \(name)"
  5. }
  6. }
  7. extension Hamster: TextRepresentable {}

Instances of Hamster can now be used wherever TextRepresentable is the required type: TextRepresentableが必要な型であるどこででも、Hamsterのインスタンスが現在使われることができます:

  1. let simonTheHamster = Hamster(name: "Simon")
  2. let somethingTextRepresentable: TextRepresentable = simonTheHamster
  3. print(somethingTextRepresentable.textualDescription)
  4. // Prints "A hamster named Simon"(「サイモンという名前のハムスター」を出力します)

Note 注意

Types don’t automatically adopt a protocol just by satisfying its requirements. They must always explicitly declare their adoption of the protocol. 型は、単にその要件を満たすことだけによっては自動的にあるプロトコルを採用しません。それらは、常に明示的にそのプロトコルについてそれらが採用することを宣言しなければなりません。

Adopting a Protocol Using a Synthesized Implementation プロトコルを合成実装を使って採用する

Swift can automatically provide the protocol conformance for Equatable, Hashable, and Comparable in many simple cases. Using this synthesized implementation means you don’t have to write repetitive boilerplate code to implement the protocol requirements yourself. スウィフトは、自動的にプロトコル準拠をEquatableHashable、そしてComparableに対して提供することが多くの単純な場合において可能です。この合成実装を使うことは、あなたが繰り返しの常用文コードを書いてプロトコル要件をあなた自身で実装する必要はないのを意味します。

Swift provides a synthesized implementation of Equatable for the following kinds of custom types: スウィフトは、Equatableの合成実装を以下の種類のあつらえの型に提供します:

  • Structures that have only stored properties that conform to the Equatable protocol Equatableプロトコルに準拠する格納プロパティだけを持つ構造体
  • Enumerations that have only associated types that conform to the Equatable protocol Equatableプロトコルに準拠する関連型だけを持つ列挙
  • Enumerations that have no associated types 関連型を持たない列挙

To receive a synthesized implementation of ==, declare conformance to Equatable in the file that contains the original declaration, without implementing an == operator yourself. The Equatable protocol provides a default implementation of !=. ==の合成実装を受け取るには、Equatableへの準拠を本来の宣言を含んでいるファイルにおいて宣言してください、==演算子をあなた自身で実装することなしに。Equatableプロトコルは、!=の省略時の実装を提供します。

The example below defines a Vector3D structure for a three-dimensional position vector (x, y, z), similar to the Vector2D structure. Because the x, y, and z properties are all of an Equatable type, Vector3D receives synthesized implementations of the equivalence operators. 下の例は、Vector3D構造体を3次元の位置ベクトル(x, y, z)に対して定義する、Vector2D構造体に似たものです。xy、そしてzプロパティはみんなEquatable型なので、Vector3Dは等価演算子の合成された実装それらを受け取ります。

  1. struct Vector3D: Equatable {
  2. var x = 0.0, y = 0.0, z = 0.0
  3. }
  4. let twoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0)
  5. let anotherTwoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0)
  6. if twoThreeFour == anotherTwoThreeFour {
  7. print("These two vectors are also equivalent.")
  8. }
  9. // Prints "These two vectors are also equivalent."(「これらの2つのベクトルはまた等しいです。」を出力します)

Swift provides a synthesized implementation of Hashable for the following kinds of custom types: スウィフトは、Hashableの合成実装を以下の種類のあつらえの型に提供します:

  • Structures that have only stored properties that conform to the Hashable protocol Hashableプロトコルに準拠する格納プロパティだけを持つ構造体
  • Enumerations that have only associated types that conform to the Hashable protocol Hashableプロトコルに準拠する関連型だけを持つ列挙
  • Enumerations that have no associated types 関連型を持たない列挙

To receive a synthesized implementation of hash(into:), declare conformance to Hashable in the file that contains the original declaration, without implementing a hash(into:) method yourself. hash(into:)の合成実装を受け取るには、Hashableへの準拠を本来の宣言を含むファイルにおいて宣言してください、hash(into:)メソッドをあなた自身で実装することなしに。

Swift provides a synthesized implementation of Comparable for enumerations that don’t have a raw value. If the enumeration has associated types, they must all conform to the Comparable protocol. To receive a synthesized implementation of <, declare conformance to Comparable in the file that contains the original enumeration declaration, without implementing a < operator yourself. The Comparable protocol’s default implementation of <=, >, and >= provides the remaining comparison operators. スウィフトは、Comparableの合成実装を生の値を持たない列挙に提供します。列挙が関連型いくつかを持つならば、それらは全てComparableプロトコルに準拠しなければなりません。<の合成実装を受け取るには、Comparableへの準拠を本来の列挙宣言を含むファイルにおいて宣言してください、<演算子をあなた自身で実装することなしに。Comparableプロトコルのもつ<=>、そして>=の省略時の実装は、残りの比較演算子を提供します。

The example below defines a SkillLevel enumeration with cases for beginners, intermediates, and experts. Experts are additionally ranked by the number of stars they have. 下の例は、SkillLevel列挙を、初心者(beginners)、中級者(intermediates)、そして熟練者(experts)に対する事例(ケース節)で定義します。expertsは加えて、彼らが持つ星の数によってランク付けされます。

  1. enum SkillLevel: Comparable {
  2. case beginner
  3. case intermediate
  4. case expert(stars: Int)
  5. }
  6. var levels = [SkillLevel.intermediate, SkillLevel.beginner,
  7. SkillLevel.expert(stars: 5), SkillLevel.expert(stars: 3)]
  8. for level in levels.sorted() {
  9. print(level)
  10. }
  11. // Prints "beginner"
  12. // Prints "intermediate"
  13. // Prints "expert(stars: 3)"
  14. // Prints "expert(stars: 5)"

Collections of Protocol Types プロトコル型のコレクション

A protocol can be used as the type to be stored in a collection such as an array or a dictionary, as mentioned in Protocols as Types. This example creates an array of TextRepresentable things: 型としてのプロトコルで言及されるように、プロトコルは型として使われることで、コレクション、例えば配列や辞書などに保管されることができます。この例は、TextRepresentableなものの配列をつくります:

  1. let things: [TextRepresentable] = [game, d12, simonTheHamster]

It’s now possible to iterate over the items in the array, and print each item’s textual description: 現在この配列の項目の上に繰り返して、各項目のもつ説明テキストを出力することが可能です:

  1. for thing in things {
  2. print(thing.textualDescription)
  3. }
  4. // A game of Snakes and Ladders with 25 squares(25ますのヘビとはしごのゲーム)
  5. // A 12-sided dice(ひとつの12面のさいころ遊び)
  6. // A hamster named Simon(サイモンという名前のハムスター)

Note that the thing constant is of type TextRepresentable. It’s not of type Dice, or DiceGame, or Hamster, even if the actual instance behind the scenes is of one of those types. Nonetheless, because it’s of type TextRepresentable, and anything that’s TextRepresentable is known to have a textualDescription property, it’s safe to access thing.textualDescription each time through the loop. thing定数が型TextRepresentableであることに注意してください。それは型Dice、またはDiceGame、またはHamsterではありません、たとえ舞台裏の実際のインスタンスがそれらの型のうちの1つであるとしてもです。それでもなお、それがTextRepresentable型であり、そして、TextRepresentableであるもの全てがtextualDescriptionプロパティを持つと知られているので、それがループの各回でthing.textualDescriptionにアクセスするのは安全です。

Protocol Inheritance プロトコル継承

A protocol can inherit one or more other protocols and can add further requirements on top of the requirements it inherits. The syntax for protocol inheritance is similar to the syntax for class inheritance, but with the option to list multiple inherited protocols, separated by commas: プロトコルは、1つ以上の他のプロトコルを継承することができて、それが継承する要件の上に、更なる要件を加えることができます。プロトコル継承のための構文は、クラス継承のための構文に似ています、しかし複数の継承されたプロトコルをコンマで区切って列記する選択肢を持ちます:

  1. protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
  2. // protocol definition goes here(プロトコル定義が、ここにきます)
  3. }

Here’s an example of a protocol that inherits the TextRepresentable protocol from above: 上のTextRepresentableプロトコルを継承するプロトコルの例は、ここにあります:

  1. protocol PrettyTextRepresentable: TextRepresentable {
  2. var prettyTextualDescription: String { get }
  3. }

This example defines a new protocol, PrettyTextRepresentable, which inherits from TextRepresentable. Anything that adopts PrettyTextRepresentable must satisfy all of the requirements enforced by TextRepresentable, plus the additional requirements enforced by PrettyTextRepresentable. In this example, PrettyTextRepresentable adds a single requirement to provide a gettable property called prettyTextualDescription that returns a String. この例は、ある新しいプロトコル、PrettyTextRepresentableを定義します、それは、TextRepresentableから継承を受けます。PrettyTextRepresentableを採用するどんなものでも、TextRepresentableによって強制される要件の全て、それに加えてPrettyTextRepresentableによって強制される追加の要件を満たさなければなりません。この例では、PrettyTextRepresentableは1つの要件を加えて、Stringを返すprettyTextualDescriptionと呼ばれる取得可能なプロパティを提供するようにします。

The SnakesAndLadders class can be extended to adopt and conform to PrettyTextRepresentable: SnakesAndLaddersクラスは、拡張されることでPrettyTextRepresentableを採用して準拠するようにできます:

  1. extension SnakesAndLadders: PrettyTextRepresentable {
  2. var prettyTextualDescription: String {
  3. var output = textualDescription + ":\n"
  4. for index in 1...finalSquare {
  5. switch board[index] {
  6. case let ladder where ladder > 0:
  7. output += "▲ "
  8. case let snake where snake < 0:
  9. output += "▼ "
  10. default:
  11. output += "○ "
  12. }
  13. }
  14. return output
  15. }
  16. }

This extension states that it adopts the PrettyTextRepresentable protocol and provides an implementation of the prettyTextualDescription property for the SnakesAndLadders type. Anything that’s PrettyTextRepresentable must also be TextRepresentable, and so the implementation of prettyTextualDescription starts by accessing the textualDescription property from the TextRepresentable protocol to begin an output string. It appends a colon and a line break, and uses this as the start of its pretty text representation. It then iterates through the array of board squares, and appends a geometric shape to represent the contents of each square: この拡張が述べるのは、それがPrettyTextRepresentableプロトコルを採用してprettyTextualDescriptionプロパティの実装をSnakesAndLadders型に提供することです。PrettyTextRepresentableであるものは何でも、またTextRepresentableでなければなりません、なのでprettyTextualDescriptionの実装は出力文字列を開始するためにTextRepresentableプロトコルからのtextualDescriptionプロパティにアクセスすることによって始まります。それはコロンと改行を追加します、そしてそれのきれいなテキスト表示のスタートとして、これを使います。それは、それからボードの正方形の配列の端から端まで繰り返して、ある幾何学形を各正方形の内容を表わすために追加します:

  • If the square’s value is greater than 0, it’s the base of a ladder, and is represented by . 正方形の値が0より大きいならば、それははしごの基部であって、によって表されます。
  • If the square’s value is less than 0, it’s the head of a snake, and is represented by . 正方形の値が0より小さいならば、それはヘビの頭であって、によって表されます。
  • Otherwise, the square’s value is 0, and it’s a “free” square, represented by . 一方、正方形の値は0ならば、それは「自由」な正方形であって、によって表されます。

The prettyTextualDescription property can now be used to print a pretty text description of any SnakesAndLadders instance: このprettyTextualDescriptionプロパティは、現在あらゆるSnakesAndLaddersインスタンスのきれいなテキスト解説を出力するために使われることができます:

  1. print(game.prettyTextualDescription)
  2. // A game of Snakes and Ladders with 25 squares:(25ますのヘビとはしごのゲーム:)
  3. // ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○

Class-Only Protocols クラス専用プロトコル

You can limit protocol adoption to class types (and not structures or enumerations) by adding the AnyObject protocol to a protocol’s inheritance list. あなたは、プロトコル採用をクラス型に制限する(つまり構造体や列挙で採用しない)ことがAnyObjectプロトコルをプロトコルのもつ継承リストに加えることによって可能です。

  1. protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
  2. // class-only protocol definition goes here(クラス専用プロトコル定義が、ここにきます)
  3. }

In the example above, SomeClassOnlyProtocol can only be adopted by class types. It’s a compile-time error to write a structure or enumeration definition that tries to adopt SomeClassOnlyProtocol. 上の例で、SomeClassOnlyProtocolはクラス型によってのみ採用されることができます。SomeClassOnlyProtocolを採用しようと試みる構造体や列挙定義を書くことは、コンパイル時エラーになります。

Note 注意

Use a class-only protocol when the behavior defined by that protocol’s requirements assumes or requires that a conforming type has reference semantics rather than value semantics. For more about reference and value semantics, see Structures and Enumerations Are Value Types and Classes Are Reference Types. クラス専用プロトコルを、そのプロトコルの要件によって定義される挙動が想定されるまたは必要とされる時、準拠する型が値意味論ではなく参照意味論を持つ時に、使ってください。参照および値意味論に関する詳細は、構造体と列挙は値型ですクラスは、参照型ですを見てください。

Protocol Composition プロトコル合成

It can be useful to require a type to conform to multiple protocols at the same time. You can combine multiple protocols into a single requirement with a protocol composition. Protocol compositions behave as if you defined a temporary local protocol that has the combined requirements of all protocols in the composition. Protocol compositions don’t define any new protocol types. ある型に複数のプロトコルに一時に従うことを要求することは、役に立つことがありえます。あなたは、プロトコル合成を使って複数のプロトコルを1つの要件に結合することができます。プロトコル合成は、あなたが全てのプロトコルの要件を結合したものをその合成物の中に持っている一時的なローカルプロトコルを定義したかのように振る舞います。プロトコル合成は、何ら新しいプロトコル型を定義しません。

Protocol compositions have the form SomeProtocol & AnotherProtocol. You can list as many protocols as you need, separating them with ampersands (&). In addition to its list of protocols, a protocol composition can also contain one class type, which you can use to specify a required superclass. プロトコル合成は、形式SomeProtocol & AnotherProtocolを持ちます。あなたは、あなたが必要とするだけ多くのプロトコルを、それらをアンパサンド(&)で隔てて列記できます。いくつかのプロトコルからなるそれのリストに加えて、あるプロトコル合成はまた1つのクラス型を含むことができます、それはあなたが必要とされるスーパークラスを指定するのに使用します。

Here’s an example that combines two protocols called Named and Aged into a single protocol composition requirement on a function parameter: ここに、関数パラメータ上でNamedAgedと呼ばれる2つのプロトコルを1つのプロトコル合成要件に結合する例があります:

  1. protocol Named {
  2. var name: String { get }
  3. }
  4. protocol Aged {
  5. var age: Int { get }
  6. }
  7. struct Person: Named, Aged {
  8. var name: String
  9. var age: Int
  10. }
  11. func wishHappyBirthday(to celebrator: Named & Aged) {
  12. print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
  13. }
  14. let birthdayPerson = Person(name: "Malcolm", age: 21)
  15. wishHappyBirthday(to: birthdayPerson)
  16. // Prints "Happy birthday, Malcolm, you're 21!"(「誕生日おめでとうマルコム、あなたは21です!」を出力します)

In this example, the Named protocol has a single requirement for a gettable String property called name. The Aged protocol has a single requirement for a gettable Int property called age. Both protocols are adopted by a structure called Person. この例において、Namedプロトコルは、取得可能なStringプロパティでnameと呼ばれるものに対するただ1つの要件を持ちます。Agedプロトコルは、取得可能なIntプロパティでageと呼ばれるものに対するただ1つの要件を持ちます。両方のプロトコルは、Personと呼ばれる構造体によって採用されます。

The example also defines a wishHappyBirthday(to:) function. The type of the celebrator parameter is Named & Aged, which means “any type that conforms to both the Named and Aged protocols.” It doesn’t matter which specific type is passed to the function, as long as it conforms to both of the required protocols. 例はまた、wishHappyBirthday(to:)関数を定義します。celebratorパラメータの型はNamed & Agedです、それは「NamedAgedプロトコルの両方に準拠する何らかの型」を意味します。どのような具体的な型が関数へ渡されるかは問題ではありません、それが必須プロトコルの両方に準拠する限りは。

The example then creates a new Person instance called birthdayPerson and passes this new instance to the wishHappyBirthday(to:) function. Because Person conforms to both protocols, this call is valid, and the wishHappyBirthday(to:) function can print its birthday greeting. この例は、それからbirthdayPersonと呼ばれる新しいPersonインスタンスをつくって、この新しいインスタンスをwishHappyBirthday(to:)関数に渡します。Personが両方のプロトコルに準拠するので、これは有効な呼び出しです、それでwishHappyBirthday(to:)関数はその誕生日のお祝いを出力できます。

Here’s an example that combines the Named protocol from the previous example with a Location class: ここに1つの例があります、それは前の例からのNamedプロトコルをLocationクラスと結び付けます:

  1. class Location {
  2. var latitude: Double
  3. var longitude: Double
  4. init(latitude: Double, longitude: Double) {
  5. self.latitude = latitude
  6. self.longitude = longitude
  7. }
  8. }
  9. class City: Location, Named {
  10. var name: String
  11. init(name: String, latitude: Double, longitude: Double) {
  12. self.name = name
  13. super.init(latitude: latitude, longitude: longitude)
  14. }
  15. }
  16. func beginConcert(in location: Location & Named) {
  17. print("Hello, \(location.name)!")
  18. }
  19. let seattle = City(name: "Seattle", latitude: 47.6, longitude: -122.3)
  20. beginConcert(in: seattle)
  21. // Prints "Hello, Seattle!"

The beginConcert(in:) function takes a parameter of type Location & Named, which means “any type that’s a subclass of Location and that conforms to the Named protocol.” In this case, City satisfies both requirements. beginConcert(in:)関数は、型Location & Namedのパラメータを1つとります、それは「Locationのサブクラスであり、Namedプロトコルに準拠する何らかの型」を意味します。この場合では、Cityは両方の要件を満たします。

Passing birthdayPerson to the beginConcert(in:) function is invalid because Person isn’t a subclass of Location. Likewise, if you made a subclass of Location that didn’t conform to the Named protocol, calling beginConcert(in:) with an instance of that type is also invalid. birthdayPersonbeginConcert(in:)関数に渡すことは無効です、なぜならPersonLocationのサブクラスではないからです。同様に、あなたがLocationのサブクラスでNamedプロトコルに準拠しないものを作成したならば、beginConcert(in:)をその型のインスタンスで呼び出すことはまた無効です。

Checking for Protocol Conformance プロトコル準拠の確認

You can use the is and as operators described in Type Casting to check for protocol conformance, and to cast to a specific protocol. Checking for and casting to a protocol follows exactly the same syntax as checking for and casting to a type: あなたは、型キャストで記述されるisas演算子を特定のプロトコルへキャストするために使うことができます。あるプロトコルについて調べたりそれにキャストすることは、ある型について調べたりキャストするのと正確に同じ構文に従います:

  • The is operator returns true if an instance conforms to a protocol and returns false if it doesn’t. is演算子は、あるインスタンスがプロトコルに準拠するならばtrueを返して、それがそうしないならばfalseを返します。
  • The as? version of the downcast operator returns an optional value of the protocol’s type, and this value is nil if the instance doesn’t conform to that protocol. as?版のダウンキャスト演算子は、そのプロトコルの型のオプショナルの値を返します、そしてインスタンスがそのプロトコルに準拠しないならばその値はnilです。
  • The as! version of the downcast operator forces the downcast to the protocol type and triggers a runtime error if the downcast doesn’t succeed. as!版のダウンキャスト演算子は、そのプロトコル型へのダウンキャストを強制して、ダウンキャストが成功しなかったならば実行時エラーの引き金を引きます。

This example defines a protocol called HasArea, with a single property requirement of a gettable Double property called area: この例は、areaと呼ばれる取得可能なDoubleプロパティである1つだけのプロパティ要件をもつ、HasAreaと呼ばれるプロトコルを定義します:

  1. protocol HasArea {
  2. var area: Double { get }
  3. }

Here are two classes, Circle and Country, both of which conform to the HasArea protocol: その両方ともHasAreaプロトコルに従う2つのクラス、CircleCountryが、ここにあります:

  1. class Circle: HasArea {
  2. let pi = 3.1415927
  3. var radius: Double
  4. var area: Double { return pi * radius * radius }
  5. init(radius: Double) { self.radius = radius }
  6. }
  7. class Country: HasArea {
  8. var area: Double
  9. init(area: Double) { self.area = area }
  10. }

The Circle class implements the area property requirement as a computed property, based on a stored radius property. The Country class implements the area requirement directly as a stored property. Both classes correctly conform to the HasArea protocol. Circleクラスはareaプロパティ要件を、格納radiusプロパティに基づいて計算プロパティとして、満たします。Countryクラスは、area要件を格納プロパティとして直接に満たします。両方のクラスは、正しくHasAreaプロトコルに従います。

Here’s a class called Animal, which doesn’t conform to the HasArea protocol: HasAreaプロトコルに従わないAnimalと呼ばれるクラスが、ここにあります:

  1. class Animal {
  2. var legs: Int
  3. init(legs: Int) { self.legs = legs }
  4. }

The Circle, Country and Animal classes don’t have a shared base class. Nonetheless, they’re all classes, and so instances of all three types can be used to initialize an array that stores values of type AnyObject: CircleCountryAnimalクラスには、共有の基盤クラスがありません。それでもなお、それらは全てクラスです、なので、3つの型全てのインスタンスは、型AnyObjectの値を格納するある配列を初期化するために使用できます:

  1. let objects: [AnyObject] = [
  2. Circle(radius: 2.0),
  3. Country(area: 243_610),
  4. Animal(legs: 4)
  5. ]

The objects array is initialized with an array literal containing a Circle instance with a radius of 2 units; a Country instance initialized with the surface area of the United Kingdom in square kilometers; and an Animal instance with four legs. objects配列は、単位2の半径をもつCircleインスタンスを含んでいる配列リテラル;平方キロメートルでの英国の面積で初期化されるCountryインスタンス;そして、4本脚のAnimalインスタンス;を含んでいる配列リテラルで初期化されます。

The objects array can now be iterated, and each object in the array can be checked to see if it conforms to the HasArea protocol: objects配列は、今や繰り返されることができます、そして配列の各オブジェクトはそれがHasAreaプロトコルに従うかどうかを確認されることができます:

  1. for object in objects {
  2. if let objectWithArea = object as? HasArea {
  3. print("Area is \(objectWithArea.area)")
  4. } else {
  5. print("Something that doesn't have an area")
  6. }
  7. }
  8. // Area is 12.5663708(面積は、12.5663708です)
  9. // Area is 243610.0(面積は、243610.0です)
  10. // Something that doesn't have an area(面積を持たない何か)

Whenever an object in the array conforms to the HasArea protocol, the optional value returned by the as? operator is unwrapped with optional binding into a constant called objectWithArea. The objectWithArea constant is known to be of type HasArea, and so its area property can be accessed and printed in a type-safe way. 配列のオブジェクトがHasAreaプロトコルに準拠するときはいつでも、as?演算子によって返されるオプショナルの値は、オプショナル束縛によってobjectWithAreaと呼ばれる定数へとアンラップされます。定数のobjectWithAreaは、型HasAreaであるということを知られています、なので、そのareaプロパティは型安全な方法でアクセスされて出力されることができます。

Note that the underlying objects aren’t changed by the casting process. They continue to be a Circle, a Country and an Animal. However, at the point that they’re stored in the objectWithArea constant, they’re only known to be of type HasArea, and so only their area property can be accessed. 根底にあるオブジェクトがキャスト処理によって変更されない点に注意してください。それらは、CircleCountry、そしてAnimalであり続けます。しかし、それらが定数のobjectWithAreaに格納される時点で、それらは型HasAreaであるということを知られているだけです、なので、それらのareaプロパティだけがアクセスされることができます。

Optional Protocol Requirements オプショナルのプロトコル要件

You can define optional requirements for protocols. These requirements don’t have to be implemented by types that conform to the protocol. Optional requirements are prefixed by the optional modifier as part of the protocol’s definition. Optional requirements are available so that you can write code that interoperates with Objective-C. Both the protocol and the optional requirement must be marked with the @objc attribute. Note that @objc protocols can be adopted only by classes that inherit from Objective-C classes or other @objc classes. They can’t be adopted by structures or enumerations. あなたは、オプショナル要件をプロトコルに対して定義できます。それらの要件は、そのプロトコルに準拠する型によって実装される必要はありません。オプショナルの要件は、そのプロトコル定義においてoptional修飾子を前に置かれます。オプショナル要件が利用可能なことから、あなたはObjective-Cと相互運用するコードを書くことができます。プロトコルとオプショナル要件の両方は、@objc属性で印されなければなりません。@objcプロトコルがObjective-Cクラスや他の@objcクラスから継承するクラスによってのみ採用される点に注意してください。それは構造体や列挙によって採用されることはできません。

When you use a method or property in an optional requirement, its type automatically becomes an optional. For example, a method of type (Int) -> String becomes ((Int) -> String)?. Note that the entire function type is wrapped in the optional, not the method’s return value. あなたがオプショナルの要件の中のメソッドやプロパティを使うとき、それの型は自動的にオプショナルになります。例えば、型(Int) -> Stringのメソッドは((Int) -> String)?になります。メソッドの戻り値ではなく、その関数型の全体がオプショナルの中のラップされることに注意してください。

An optional protocol requirement can be called with optional chaining, to account for the possibility that the requirement was not implemented by a type that conforms to the protocol. You check for an implementation of an optional method by writing a question mark after the name of the method when it’s called, such as someOptionalMethod?(someArgument). For information on optional chaining, see Optional Chaining. オプショナルのプロトコル要件は、オプショナル連鎖を使って呼び出されることができます、それによってプロトコルに準拠する型によって要件が満たされなかったという可能性に対応します。あなたは、それが呼ばれるときに疑問符をそのメソッドの後に書くことによって、あるオプショナルメソッドの実装について確認することができます、例えばsomeOptionalMethod?(someArgument)のように。オプショナル連鎖に関する情報のために、オプショナル連鎖を見てください。

The following example defines an integer-counting class called Counter, which uses an external data source to provide its increment amount. This data source is defined by the CounterDataSource protocol, which has two optional requirements: 以下の例はCounterと呼ばれる整数計数クラスを定義します、それは、その増加量を提供するために外部のデータ・ソースを使います。このデータ・ソースはCounterDataSourceプロトコルによって定義されます、それは、2つのオプショナルの要件を持ちます:

  1. @objc protocol CounterDataSource {
  2. @objc optional func increment(forCount count: Int) -> Int
  3. @objc optional var fixedIncrement: Int { get }
  4. }

The CounterDataSource protocol defines an optional method requirement called increment(forCount:) and an optional property requirement called fixedIncrement. These requirements define two different ways for data sources to provide an appropriate increment amount for a Counter instance. CounterDataSourceプロトコルは、incrementForCount(_:)と呼ばれるオプショナルのメソッド要件とfixedIncrementと呼ばれるオプショナルのプロパティ要件を定義します。これらの要件は、データ・ソースのためにCounterインスタンスに適切な増加量を用意する2つの異なる方法を定義します。

Note 注意

Strictly speaking, you can write a custom class that conforms to CounterDataSource without implementing either protocol requirement. They’re both optional, after all. Although technically allowed, this wouldn’t make for a very good data source. 厳密に言って、あなたはCounterDataSourceに準拠する特注のクラスを書くことが両方のプロトコル要件を満たすことなく可能です。結局、それらは両方ともオプショナルです。技術的には可能であるけれども、これはあまり良いデータ・ソースにつながりません。

The Counter class, defined below, has an optional dataSource property of type CounterDataSource?: 下で定義される、Counterクラスは、型CounterDataSource?のオプショナルのdataSourceプロパティを持ちます:

  1. class Counter {
  2. var count = 0
  3. var dataSource: CounterDataSource?
  4. func increment() {
  5. if let amount = dataSource?.increment?(forCount: count) {
  6. count += amount
  7. } else if let amount = dataSource?.fixedIncrement {
  8. count += amount
  9. }
  10. }
  11. }

The Counter class stores its current value in a variable property called count. The Counter class also defines a method called increment, which increments the count property every time the method is called. Counterクラスは、その現在の値をcountと呼ばれる変数プロパティに保管します。Counterクラスはまた、incrementと呼ばれるメソッドを定義します、それは、メソッドが呼ばれるたびにcountプロパティを増加させます。

The increment() method first tries to retrieve an increment amount by looking for an implementation of the increment(forCount:) method on its data source. The increment() method uses optional chaining to try to call increment(forCount:), and passes the current count value as the method’s single argument. increment()メソッドは、最初にそれのデータ・ソース上でincrement(forCount:)メソッドの実装を捜すことによって増加量を取り出そうと試みます。increment()メソッドは、オプショナル連鎖を使ってincrement(forCount:)を呼ぶことを試みます、そしてメソッドのもつただ1つの引数として現在のcount値を渡します。

Note that two levels of optional chaining are at play here. First, it’s possible that dataSource may be nil, and so dataSource has a question mark after its name to indicate that increment(forCount:) should be called only if dataSource isn’t nil. Second, even if dataSource does exist, there’s no guarantee that it implements increment(forCount:), because it’s an optional requirement. Here, the possibility that increment(forCount:) might not be implemented is also handled by optional chaining. The call to increment(forCount:) happens only if increment(forCount:) exists—that is, if it isn’t nil. This is why increment(forCount:) is also written with a question mark after its name. ここで2つの階層のオプショナル連鎖が働いていることに注意してください。第1に、dataSourcenilかもしれない可能性があります、なので、dataSourceはその名前の後に疑問符を持ち、dataSourcenilでない場合にのみincrement(forCount:)が呼ばれるべきであるのを示します。第2に、たとえdataSource存在するとしても、それがincrement(forCount:)を実装する保証はありません、それがオプショナルの要件であるからです。ここでは、increment(forCount:)が実装されないかもしれないという可能性もまたオプショナル連鎖によって取り扱われます。increment(forCount:)への呼び出しは、increment(forCount:)が存在する場合にのみ起こります ― すなわち、それがnilでない場合。これが、increment(forCount:)もまたその名前の後に疑問符を書かれる理由です。

Because the call to increment(forCount:) can fail for either of these two reasons, the call returns an optional Int value. This is true even though increment(forCount:) is defined as returning a non-optional Int value in the definition of CounterDataSource. Even though there are two optional chaining operations, one after another, the result is still wrapped in a single optional. For more information about using multiple optional chaining operations, see Linking Multiple Levels of Chaining. increment(forCount:)への呼び出しがこれらの2つの理由のどちらによっても失敗する可能性があるので、呼び出しはオプショナルの Int値を返します。たとえincrement(forCount:)CounterDataSourceの定義の中で非オプショナルのInt値を返すように定義されるとしても、これは当てはまります。たとえ2つのオプショナル連鎖演算があったとしても、後から後から、その結果は依然としてただ1つのオプショナルの中にラップされます。複数のオプショナル連鎖演算を使用することについての更なる情報として、連鎖の複数の階層を結ぶを見てください。

After calling increment(forCount:), the optional Int that it returns is unwrapped into a constant called amount, using optional binding. If the optional Int does contain a value—that is, if the delegate and method both exist, and the method returned a value—the unwrapped amount is added onto the stored count property, and incrementation is complete. increment(forCount:)呼び出しの後、それが返すオプショナルのIntは、オプショナル束縛を使って、amountと呼ばれる定数へとアンラップされます。オプショナルのIntが値を含むならば ― すなわち、委任先とメソッドが両方とも存在する、そしてメソッドが値を返すならば ― アンラップされたamountが格納countプロパティへと加えられます、そして増加作業は完了です。

If it’s not possible to retrieve a value from the increment(forCount:) method—either because dataSource is nil, or because the data source doesn’t implement increment(forCount:)—then the increment() method tries to retrieve a value from the data source’s fixedIncrement property instead. The fixedIncrement property is also an optional requirement, so its value is an optional Int value, even though fixedIncrement is defined as a non-optional Int property as part of the CounterDataSource protocol definition. 値をincrement(forCount:)メソッドから取り出すことが可能でないならば ― dataSourceがnilであるから、またはデータ・ソースがincrement(forCount:)を実装しないからのどちらでも ― その時increment()メソッドはその代わりに値をデータ・ソースのfixedIncrementプロパティから取り出そうとします。fixedIncrementプロパティもまたオプショナルの要件です、なのでその値はオプショナルのInt値です、たとえfixedIncrementが非オプショナルのIntプロパティであるとCounterDataSourceプロトコル定義の部分では定義されるとしてもです。

Here’s a simple CounterDataSource implementation where the data source returns a constant value of 3 every time it’s queried. It does this by implementing the optional fixedIncrement property requirement: ある単純なCounterDataSource実装がここにあります、そこにおいて、データ・ソースは3の定数値をそれが問い合わされるたびに返します。それは、オプショナルのfixedIncrementプロパティ要件を実装することによってこれをします:

  1. class ThreeSource: NSObject, CounterDataSource {
  2. let fixedIncrement = 3
  3. }

You can use an instance of ThreeSource as the data source for a new Counter instance: あなたは、ThreeSourceのインスタンスを新しいCounterインスタンスのためのデータ・ソースとして使うことができます:

  1. var counter = Counter()
  2. counter.dataSource = ThreeSource()
  3. for _ in 1...4 {
  4. counter.increment()
  5. print(counter.count)
  6. }
  7. // 3
  8. // 6
  9. // 9
  10. // 12

The code above creates a new Counter instance; sets its data source to be a new ThreeSource instance; and calls the counter’s increment() method four times. As expected, the counter’s count property increases by three each time increment() is called. 上のコードは、新しいCounterインスタンスをつくり;それのデータ・ソースを新しいThreeSourceインスタンスであるように設定します;そして、counterのincrement()メソッドを4回呼び出します。予想されるように、counterのcountプロパティは、increment()が呼ばれるたびに3つずつ増加します。

Here’s a more complex data source called TowardsZeroSource, which makes a Counter instance count up or down towards zero from its current count value: TowardsZeroSourceと呼ばれるより複雑なデータ・ソースがここにあります、それは、Counterインスタンスをその現在のcount値から上下にゼロの方へ数えます:

  1. class TowardsZeroSource: NSObject, CounterDataSource {
  2. func increment(forCount count: Int) -> Int {
  3. if count == 0 {
  4. return 0
  5. } else if count < 0 {
  6. return 1
  7. } else {
  8. return -1
  9. }
  10. }
  11. }

The TowardsZeroSource class implements the optional increment(forCount:) method from the CounterDataSource protocol and uses the count argument value to work out which direction to count in. If count is already zero, the method returns 0 to indicate that no further counting should take place. TowardsZeroSourceクラスは、CounterDataSourceプロトコルからのオプショナルのincrement(forCount:)メソッドを実装して、どの方向に数えるべきか解決するためにcount引数値を使います。countがすでにゼロであるならば、メソッドは0を返して、これ以上数えることは必要ないことを示します。

You can use an instance of TowardsZeroSource with the existing Counter instance to count from -4 to zero. Once the counter reaches zero, no more counting takes place: あなたは、TowardsZeroSourceのインスタンスを既存のCounterインスタンスとともに使って、-4からゼロへと数えることができます。ひとたびcounterがゼロに達するならば、それ以上数えることは起こりません:

  1. counter.count = -4
  2. counter.dataSource = TowardsZeroSource()
  3. for _ in 1...5 {
  4. counter.increment()
  5. print(counter.count)
  6. }
  7. // -3
  8. // -2
  9. // -1
  10. // 0
  11. // 0

Protocol Extensions プロトコル拡張

Protocols can be extended to provide method, initializer, subscript, and computed property implementations to conforming types. This allows you to define behavior on protocols themselves, rather than in each type’s individual conformance or in a global function. プロトコルは拡張されることによって、準拠している型にメソッド、イニシャライザ、添え字、そして計算プロパティの実装を提供できます。これはあなたに、それぞれの型の個々の準拠においてまたはグローバル関数においてではなく、プロトコルそれ自体に振る舞いを定義することを可能にします。

For example, the RandomNumberGenerator protocol can be extended to provide a randomBool() method, which uses the result of the required random() method to return a random Bool value: 例えば、RandomNumberGeneratorプロトコルは拡張されてrandomBool()メソッドを提供することができます、それは必須メソッドのrandom()を利用してランダムなBool値を返すものです:

  1. extension RandomNumberGenerator {
  2. func randomBool() -> Bool {
  3. return random() > 0.5
  4. }
  5. }

By creating an extension on the protocol, all conforming types automatically gain this method implementation without any additional modification. 拡張をプロトコル上に作成することによって、すべての準拠している型が自動的にこのメソッド実装をなんら追加の修正なしに手に入れます。

  1. let generator = LinearCongruentialGenerator()
  2. print("Here's a random number: \(generator.random())")
  3. // Prints "Here's a random number: 0.3746499199817101"(「ここに任意の数: 0.3746499199817101があります」を出力します)
  4. print("And here's a random Boolean: \(generator.randomBool())")
  5. // Prints "And here's a random Boolean: true"(「そしてここに任意のブール: trueがあります」を出力します)

Protocol extensions can add implementations to conforming types but can’t make a protocol extend or inherit from another protocol. Protocol inheritance is always specified in the protocol declaration itself. プロトコル拡張は、実装を加えることによって型に準拠が可能です、しかしあるプロトコルを別のプロトコルから拡張したり継承したりはできません。プロトコル継承は、常にプロトコル宣言それ自体の中で指定されます。

Providing Default Implementations 省略時の実装を提供する

You can use protocol extensions to provide a default implementation to any method or computed property requirement of that protocol. If a conforming type provides its own implementation of a required method or property, that implementation will be used instead of the one provided by the extension. あなたはプロトコル拡張を使うことで省略時の実装をそのプロトコルのどのメソッドまたは計算プロパティ要件に対しても提供できます。準拠している型がある必須のメソッドやプロパティのそれ自身の実装を提供する場合は、その実装が拡張によって提供されるものの代わりに使用されます。

Note 注意

Protocol requirements with default implementations provided by extensions are distinct from optional protocol requirements. Although conforming types don’t have to provide their own implementation of either, requirements with default implementations can be called without optional chaining. 拡張によって提供される省略時の実装を持つプロトコル要件は、オプショナルプロトコル要件とは異なったものです。どちらにおいても準拠する型がそれ自身の実装を提供しなくても良いけれども、省略時の実装を持つ要件はオプショナル連鎖なしに呼ばれることができます。

For example, the PrettyTextRepresentable protocol, which inherits the TextRepresentable protocol can provide a default implementation of its required prettyTextualDescription property to simply return the result of accessing the textualDescription property: 例えば、TextRepresentableプロトコルを継承するprettyTextualDescriptionプロパティは、それの必須プロパティprettyTextualDescriptionの省略時の実装を提供して、単にtextualDescriptionプロパティの結果を返すようにできます:

  1. extension PrettyTextRepresentable {
  2. var prettyTextualDescription: String {
  3. return textualDescription
  4. }
  5. }

Adding Constraints to Protocol Extensions プロトコル拡張に制約を加える

When you define a protocol extension, you can specify constraints that conforming types must satisfy before the methods and properties of the extension are available. You write these constraints after the name of the protocol you’re extending by writing a generic where clause. For more about generic where clauses, see Generic Where Clauses. あなたがプロトコル拡張を定義するとき、あなたは準拠している型がその拡張のメソッドやプロパティが利用可能になる前に満たさなければならない制約を指定することができます。あなたはこれらの制約を、総称体where節を書くことによってあなたが拡張しているプロトコルの名前の後に書きます。総称体where節に関する詳細は、総称体where節を見てください。

For example, you can define an extension to the Collection protocol that applies to any collection whose elements conform to the Equatable protocol. By constraining a collection’s elements to the Equatable protocol, a part of the standard library, you can use the == and != operators to check for equality and inequality between two elements. 例えば、それの要素がEquatableプロトコルに準拠するあらゆるコレクションに適用されるCollectionプロトコルに対して、あなたはある拡張を定義できます。あるコレクションの持つ要素をEquatableプロトコル、標準ライブラリの1つ、に制約することで、あなたは==!=演算子を使って同等性と同一性を2つの要素間で確認できます。

  1. extension Collection where Element: Equatable {
  2. func allEqual() -> Bool {
  3. for element in self {
  4. if element != self.first {
  5. return false
  6. }
  7. }
  8. return true
  9. }
  10. }

The allEqual() method returns true only if all the elements in the collection are equal. allEqual()メソッドがtrueを返すのは、そのコレクションの中の要素すべてが同等である場合のみです。

Consider two arrays of integers, one where all the elements are the same, and one where they aren’t: いくつかの整数からなる2つの配列を考えてください、すべての要素が同じであるもの、そしてそうではないもの:

  1. let equalNumbers = [100, 100, 100, 100, 100]
  2. let differentNumbers = [100, 100, 200, 100, 200]

Because arrays conform to Collection and integers conform to Equatable, equalNumbers and differentNumbers can use the allEqual() method: それら配列はCollectionに準拠し、それら整数はEquatableに準拠することから、equalNumbersdifferentNumbersallEqual()メソッドを使うことができます:

  1. print(equalNumbers.allEqual())
  2. // Prints "true"(「true」を出力します)
  3. print(differentNumbers.allEqual())
  4. // Prints "false"(「false」を出力します)

Note 注意

If a conforming type satisfies the requirements for multiple constrained extensions that provide implementations for the same method or property, Swift uses the implementation corresponding to the most specialized constraints. ある準拠型が同じメソッドやプロパティに対する実装を提供する複数の制約拡張に対する要件を満たすならば、スウィフトは最も特殊化した制約と一致する実装を使います。

Extensions 拡張

Generics 総称体