Extensions¶ 拡張¶
Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you don’t have access to the original source code (known as retroactive modeling). Extensions are similar to categories in Objective-C. (Unlike Objective-C categories, Swift extensions don’t have names.) 拡張は、新しい機能性を既存のクラス、構造体、列挙、またはプロトコル型に加えます。これは、あなたが元々のソース・コードにアクセスをしないで型を拡張する能力を含みます(遡及モデリングとして知られます)。拡張は、Objective-Cでのカテゴリーに似ています。(Objective-Cカテゴリーとは異なり、スウィフト拡張には、名前がありません。)
Extensions in Swift can: スウィフトの拡張は、以下が可能です:
- Add computed instance properties and computed type properties 計算インスタンスプロパティと計算型プロパティを加える
- Define instance methods and type methods インスタンスメソッドと型メソッドを定義する
- Provide new initializers 新しいイニシャライザを提供する
- Define subscripts 添え字を定義する
- Define and use new nested types 新しい入れ子にされた型を定義して、使用する
- Make an existing type conform to a protocol 既存の型をプロトコルに準拠させる
In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions. スウィフトでは、あなたはプロトコルを拡張してその要件の実装を提供することやそれの準拠型が利用することができる追加の機能性を加えることさえ可能です。詳細は、プロトコル拡張を見てください。
Note 注意
Extensions can add new functionality to a type, but they can’t override existing functionality. 拡張は、新しい機能性をある型に加えることができます、しかしそれは既存の機能性をオーバーライドすることはできません。
Extension Syntax¶ 拡張構文¶
Declare extensions with the extension
keyword:
extension
キーワードによって拡張を宣言してください:
- extension SomeType {
- // new functionality to add to SomeType goes here(SomeTypeに加える新しい機能性が、ここにきます)
- }
An extension can extend an existing type to make it adopt one or more protocols. To add protocol conformance, you write the protocol names the same way as you write them for a class or structure: 拡張は、既存の型を拡張して、それが1つ以上のプロトコルを採用するようにできます。プロトコル準拠を加えるには、あなたはそれらプロトコル名を、あなたがそれらをクラスや構造体に対して書くのと同じ方法で記述します。
- extension SomeType: SomeProtocol, AnotherProtocol {
- // implementation of protocol requirements goes here(プロトコル要件の実装が、ここにきます)
- }
Adding protocol conformance in this way is described in Adding Protocol Conformance with an Extension. この方法でプロトコル準拠を加えることは拡張を使ってプロトコル準拠を加えるで記述されます。
An extension can be used to extend an existing generic type, as described in Extending a Generic Type. You can also extend a generic type to conditionally add functionality, as described in Extensions with a Generic Where Clause. 拡張は、既存の総称体型を拡張するために使われることができます、総称体型を拡張するで記述されるように。あなたはまた総称体型を拡張することで条件付きの機能性を追加することができます、総称体where節を持つ拡張で記述されるように。
Note 注意
If you define an extension to add new functionality to an existing type, the new functionality will be available on all existing instances of that type, even if they were created before the extension was defined. あなたが新しい機能性を既存の型に加えるために拡張を定義するならば、新しい機能性はその型の全ての既存の例で利用可能になります、たとえそれらが拡張が定義される前につくられたとしてもです。
Computed Properties¶ 計算プロパティ¶
Extensions can add computed instance properties and computed type properties to existing types. This example adds five computed instance properties to Swift’s built-in Double
type, to provide basic support for working with distance units:
拡張は、既存の型に計算インスタンスプロパティと計算型プロパティを加えることができます。この例は、5つの計算インスタンスプロパティをスウィフトの組み込みのDouble
型に加えて、距離単位を扱うための基本的な支持を提供します:
- extension Double {
- var km: Double { return self * 1_000.0 }
- var m: Double { return self }
- var cm: Double { return self / 100.0 }
- var mm: Double { return self / 1_000.0 }
- var ft: Double { return self / 3.28084 }
- }
- let oneInch = 25.4.mm
- print("One inch is \(oneInch) meters")
- // Prints "One inch is 0.0254 meters"(「1インチは、0.0254メートルです」を出力します)
- let threeFeet = 3.ft
- print("Three feet is \(threeFeet) meters")
- // Prints "Three feet is 0.914399970739201 meters"(「3フィートは、0.914399970739201メートルです」を出力します)
These computed properties express that a Double
value should be considered as a certain unit of length. Although they’re implemented as computed properties, the names of these properties can be appended to a floating-point literal value with dot syntax, as a way to use that literal value to perform distance conversions.
これらの計算プロパティは、Double
値が長さの特定の単位とみなされなければならないことを表します。それらは計算プロパティとして実装されるけれども、これらのプロパティの名前はある浮動小数点リテラル値に、そのリテラル値を距離変換を実行するために使う方法として、ドット構文で追加されることが可能です。
In this example, a Double
value of 1.0
is considered to represent “one meter”. This is why the m
computed property returns self
—the expression 1.m
is considered to calculate a Double
value of 1.0
.
この例では、1.0
のDouble
値は「1メートル」を表すと考慮されます。これがm
計算プロパティがself
を返す理由です ― 式1.m
は、1.0
のDouble
値を計算するものと考えられます。
Other units require some conversion to be expressed as a value measured in meters. One kilometer is the same as 1,000 meters, so the km
computed property multiplies the value by 1_000.00
to convert into a number expressed in meters. Similarly, there are 3.28084 feet in a meter, and so the ft
computed property divides the underlying Double
value by 3.28084
, to convert it from feet to meters.
他の単位は、メートルで計られる値として表されるためにいくらかの変換を必要とします。1キロメートルは1,000メートルと同じものですので、km
計算プロパティは1_000.00
を掛けられて、メートルで表される数に変換されます。同じように、1メートルは3.28084フィートあります、なのでft
計算プロパティは、もとのDouble
値を3.28084
で割って、それをフィートからメートルに変換します。
These properties are read-only computed properties, and so they’re expressed without the get
keyword, for brevity. Their return value is of type Double
, and can be used within mathematical calculations wherever a Double
is accepted:
これらのプロパティは、読み出し専用の計算プロパティです、それでそれらは簡潔さのために、get
キーワードなしで表わされます。それらの戻り値はDouble
型です、そして数学計算内のDouble
が受け入れられるあらゆるところで使われることができます:
- let aMarathon = 42.km + 195.m
- print("A marathon is \(aMarathon) meters long")
- // Prints "A marathon is 42195.0 meters long"(「マラソンは、42195.0メートルの長さです」を出力します)
Note 注意
Extensions can add new computed properties, but they can’t add stored properties, or add property observers to existing properties. 拡張は新しい計算プロパティを加えることができます、しかし、それは格納プロパティを加えることができません、またプロパティオブザーバーを既存のプロパティに加えることができません。
Initializers¶ イニシャライザ¶
Extensions can add new initializers to existing types. This enables you to extend other types to accept your own custom types as initializer parameters, or to provide additional initialization options that were not included as part of the type’s original implementation. 拡張は、新しいイニシャライザを既存の型に加えることができます。これは、あなたに別の型を拡張してあなた独自のあつらえの型をイニシャライザパラメータとして受け入れるようにすること、またはその型の最初の実装の一部として含まれなかった追加の初期化選択肢を提供することを可能にします。
Extensions can add new convenience initializers to a class, but they can’t add new designated initializers or deinitializers to a class. Designated initializers and deinitializers must always be provided by the original class implementation. 拡張は、新しい便利なイニシャライザをクラスに加えることができます、しかし、それは新しい指定イニシャライザまたはデイニシャライザをクラスに加えることができません。指定イニシャライザとデイニシャライザは、常に最初のクラス実施によって提供されなければなりません。
If you use an extension to add an initializer to a value type that provides default values for all of its stored properties and doesn’t define any custom initializers, you can call the default initializer and memberwise initializer for that value type from within your extension’s initializer. This wouldn’t be the case if you had written the initializer as part of the value type’s original implementation, as described in Initializer Delegation for Value Types. あなたが拡張を、その格納プロパティの全てに省略時の値を与えて全くあつらえのイニシャライザを定義しない値型に、イニシャライザを加えるために使うならば、あなたはその値型のための省略時のイニシャライザとメンバー関連イニシャライザを、あなたの拡張のイニシャライザ内から呼ぶことができます。値型のためのイニシャライザ委任で記述されるように、あなたがイニシャライザをその値型の最初の実装の一部として書いたならば、それはこの場合にはなりません。
If you use an extension to add an initializer to a structure that was declared in another module, the new initializer can’t access self
until it calls an initializer from the defining module.
あなたが拡張を使ってイニシャライザを別のモジュールの中で宣言された構造体へと加えるならば、その新しいイニシャライザはself
にアクセスすることが、それがあるイニシャライザを定義されているモジュールから呼び出すまでは出来ません。
The example below defines a custom Rect
structure to represent a geometric rectangle. The example also defines two supporting structures called Size
and Point
, both of which provide default values of 0.0
for all of their properties:
下の例は、幾何学の長方形を表すためにあつらえのRect
構造体を定義します。この例はまた、Size
とPoint
と呼ばれる2つの支援の構造体を定義します、その両方はそれらのプロパティの全てに0.0
の省略時の値を提供します:
- struct Size {
- var width = 0.0, height = 0.0
- }
- struct Point {
- var x = 0.0, y = 0.0
- }
- struct Rect {
- var origin = Point()
- var size = Size()
- }
Because the Rect
structure provides default values for all of its properties, it receives a default initializer and a memberwise initializer automatically, as described in Default Initializers. These initializers can be used to create new Rect
instances:
Rect
構造体がそのプロパティの全てに省略時の値を与えるので、省略時のイニシャライザで記述されるように、それは自動的に省略時のイニシャライザとメンバー関連イニシャライザを受け取ります。これらのイニシャライザが、新しいRect
例をつくるために使われることができます:
- let defaultRect = Rect()
- let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
- size: Size(width: 5.0, height: 5.0))
You can extend the Rect
structure to provide an additional initializer that takes a specific center point and size:
あなたは、Rect
構造体を拡張して、特定の中心点と大きさをとる追加のイニシャライザを提供することができます:
- extension Rect {
- init(center: Point, size: Size) {
- let originX = center.x - (size.width / 2)
- let originY = center.y - (size.height / 2)
- self.init(origin: Point(x: originX, y: originY), size: size)
- }
- }
This new initializer starts by calculating an appropriate origin point based on the provided center
point and size
value. The initializer then calls the structure’s automatic memberwise initializer init(origin:size:)
, which stores the new origin and size values in the appropriate properties:
この新しいイニシャライザは、提供されたcenter
点とsize
値に基づいて適切な起源点を計算することによって始めます。イニシャライザはそれから、構造体の自動的なメンバー関連イニシャライザinit(origin:size:)
を呼びます、それは、新しい原点とサイズ値を適切なプロパティに保管します:
- let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
- size: Size(width: 3.0, height: 3.0))
- // centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)(centerRectの原点は(2.5, 2.5)、そのサイズは(3.0, 3.0)です)
Note 注意
If you provide a new initializer with an extension, you are still responsible for making sure that each instance is fully initialized once the initializer completes. あなたが新しいイニシャライザを拡張によって提供する場合、あなたは依然として、一旦イニシャライザが完了するならば各インスタンスが完全に初期化されることを確かにする責任があります。
Methods¶ メソッド¶
Extensions can add new instance methods and type methods to existing types. The following example adds a new instance method called repetitions
to the Int
type:
拡張は、新しいインスタンスメソッドと型メソッドを既存の型に加えることができます。以下の例は、repetitions
と呼ばれる新しいインスタンスメソッドをInt
型に加えます:
- extension Int {
- func repetitions(task: () -> Void) {
- for _ in 0..<self {
- task()
- }
- }
- }
The repetitions(task:)
method takes a single argument of type () -> Void
, which indicates a function that has no parameters and doesn’t return a value.
repetitions(task:)
メソッドは型() -> Void
の引数をひとつだけとります、それは、パラメータを持たず、値を返さない関数であることを示します。
After defining this extension, you can call the repetitions(task:)
method on any integer to perform a task that many number of times:
この拡張を定義した後、あなたはrepetitions(task:)
メソッドをあらゆる整数上で呼び出して、ある作業をそれだけ多くの回数実行できます:
- 3.repetitions {
- print("Hello!")
- }
- // Hello!
- // Hello!
- // Hello!
Mutating Instance Methods¶ 変更インスタンスメソッド¶
Instance methods added with an extension can also modify (or mutate) the instance itself. Structure and enumeration methods that modify self
or its properties must mark the instance method as mutating
, just like mutating methods from an original implementation.
拡張を使って加えられるインスタンスメソッドは、また、インスタンスそれ自体を修正(または変更)することができます。self
またはそのプロパティを修正する構造および列挙メソッドは、ちょうど最初の実施からの変更メソッドのように、そのインスタンスメソッドにmutating
として印されなければなりません。
The example below adds a new mutating method called square
to Swift’s Int
type, which squares the original value:
下の例は、square
と呼ばれる新しい変更メソッドをスウィフトのInt
型に加えます、それは、もとの値を二乗します:
- extension Int {
- mutating func square() {
- self = self * self
- }
- }
- var someInt = 3
- someInt.square()
- // someInt is now 9(someIntは、現在9です)
Subscripts¶ 添え字¶
Extensions can add new subscripts to an existing type. This example adds an integer subscript to Swift’s built-in Int
type. This subscript [n]
returns the decimal digit n
places in from the right of the number:
拡張は、新しい添え字を既存の型に加えることができます。この例は、整数添え字をスウィフトの組み込みのInt
型に加えます。この添え字[n]
は、右の数からの10進桁n
位置を返します:
123456789[0]
returns9
123456789[0]
は9
を返します123456789[1]
returns8
123456789[1]
は8
を返します
…and so on: …などなど:
- extension Int {
- subscript(digitIndex: Int) -> Int {
- var decimalBase = 1
- for _ in 0..<digitIndex {
- decimalBase *= 10
- }
- return (self / decimalBase) % 10
- }
- }
- 746381295[0]
- // returns 5(5を返します)
- 746381295[1]
- // returns 9(9を返します)
- 746381295[2]
- // returns 2(2を返します)
- 746381295[8]
- // returns 7(7を返します)
If the Int
value doesn’t have enough digits for the requested index, the subscript implementation returns 0
, as if the number had been padded with zeros to the left:
Int
値には要十分な桁が請されたインデックスに対してないならば、この添え字実装は、まるで数が左にゼロを詰められたように0
を返します:
- 746381295[9]
- // returns 0, as if you had requested:(まるであなたが次のように要請したかのように、0を返します:)
- 0746381295[9]
Nested Types¶ 入れ子にされた型¶
Extensions can add new nested types to existing classes, structures, and enumerations: 拡張は、新しい入れ子にされた型を既存のクラス、構造体、および列挙に加えることができます:
- extension Int {
- enum Kind {
- case negative, zero, positive
- }
- var kind: Kind {
- switch self {
- case 0:
- return .zero
- case let x where x > 0:
- return .positive
- default:
- return .negative
- }
- }
- }
This example adds a new nested enumeration to Int
. This enumeration, called Kind
, expresses the kind of number that a particular integer represents. Specifically, it expresses whether the number is negative, zero, or positive.
この例は、新しい入れ子にされた列挙をInt
に加えます。この列挙は、Kind
と呼ばれ、特定の整数を表わす数の種類を表わします。具体的には、それはその数が負、ゼロ、または正かを表わします。
This example also adds a new computed instance property to Int
, called kind
, which returns the appropriate Kind
enumeration case for that integer.
この例はまた、新しい計算インスタンスプロパティをInt
に加えます、それは、kind
と呼ばれ、その整数に対する適切なKind
列挙ケース節を返します。
The nested enumeration can now be used with any Int
value:
入れ子にされた列挙は今やあらゆるInt
値で使われることができます:
- func printIntegerKinds(_ numbers: [Int]) {
- for number in numbers {
- switch number.kind {
- case .negative:
- print("- ", terminator: "")
- case .zero:
- print("0 ", terminator: "")
- case .positive:
- print("+ ", terminator: "")
- }
- }
- print("")
- }
- printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
- // Prints "+ + - 0 - 0 + "
This function, printIntegerKinds(_:)
, takes an input array of Int
values and iterates over those values in turn. For each integer in the array, the function considers the kind
computed property for that integer, and prints an appropriate description.
この関数、printIntegerKinds(_:)
は、Int
値の配列の入力を取り、それらの値に最初から終わりまで順番に繰り返していきます。その配列の各整数に対して、この関数はその整数に対するkind
計算プロパティを考慮して、適切な説明を出力します。
Note 注意
number.kind
is already known to be of type Int.Kind
. Because of this, all of the Int.Kind
case values can be written in shorthand form inside the switch
statement, such as .negative
rather than Int.Kind.negative
.
number.kind
は、既に型Int.Kind
であると知られます。そのことから、Int.Kind
のケース節の値の全ては、switch
文内で略記形式で書かれることができます、たとえばInt.Kind.negative
ではなく.negative
のように。