拡張機能
日本語を消す 英語を消す下記URLから引用し、日本語訳をつけてみました。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/extensions
Add functionality to an existing type.
既存のタイプに機能を追加します
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 カテゴリとは異なり、Swift 拡張機能には名前がありません。)
Extensions in Swift can:
Swift の拡張機能では次のことができます。
- 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.
Swift では、プロトコルを拡張してその要件の実装を提供したり、準拠する型が利用できる機能を追加したりすることもできます。 詳細については、「プロトコル拡張」を参照してください。
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
}
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 つの計算インスタンス プロパティを Swift の組み込み 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"
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters")
// Prints "Three feet is 0.914399970739201 meters"
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
.
この例では、Double
値 1.0
は「1 メートル」を表すものとみなされます。 これが、m
計算プロパティが self
を返す理由です。式 1.m
は Double
値 1.0
を計算するとみなされます。
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"
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)
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
型の引数を 1 つ受け取ります。これは、パラメーターがなく、値を返さない関数を示します。
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
と呼ばれる新しい変更メソッドを Swift の Int
型に追加し、元の値を 2 乗します。
extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
// someInt is now 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:
拡張機能では、既存の型に新しい添字を追加できます。 この例では、Swift の組み込み Int
型に整数の添字を追加します。 この添字 [n
] は、数値の右から n
番目の 10 進数を返します。
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
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 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:
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.
この例では、kind
という新しい計算インスタンス プロパティを Int
に追加します。これは、その整数に適切な 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
case 値は、switch
ステートメント内に、Int.Kind.negative
ではなく .negative
などの省略形で記述することができます。