クラスと構造体では、既存の演算子の独自実装を提供することができます。これは、既存の演算子のオーバーロードとして知られています。
以降の例では、構造体に対する算術加算演算子 (+
) の実装方法を示しています。算術加算演算子は、2 つのターゲットに対して作用するため二項演算子で、2 つのターゲットの間に置かれるため中置 (infix) と言われます。
この例では、2 次元位置ベクトル (x, y)
の構造体 Vector2D
の定義に続けて、構造体 Vector2D
のインスタンスを合わせて加算する関数演算子を定義しています。
struct Vector2D {
var x = 0.0, y = 0.0
}
func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
演算子関数は、オーバーロードされた演算子 (+
) にマッチする関数名で、グローバル関数として定義されています。算術加算演算子は二項演算子であるため、この演算子関数は Vector2D
型の入力パラメータを 2 つ取り、Vector2D
型の出力値を返しています。
この実装では、+
演算子の左側と右側になる Vector2D
インスタンスを表現するために、入力パラメータに left
と right
と名付けています。この関数は、2 つの Vector2D
インスタンスの x
プロパティおよび y
プロパティを合わせて加算した合計で、x
プロパティと y
プロパティを初期化した新しい Vector2D
インスタンスを返しています。
この関数は、構造体 Vector2D
のメソッドとしてではなく、グローバルに定義されているため、既存の Vector2D
インスタンス間での中置演算子として使用することができます。
let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector
// combinedVector は Vector2D インスタンスで、値は (5.0, 5.0)
この例では、次の図のように、ベクトル (3.0, 1.0)
と (2.0, 4.0)
を合わせて加算し、ベクトル (5.0, 5.0)
にしています。
前置演算子と後置演算子
上の例では、二項中置演算子の実装を見てきました。クラスと構造体では、標準の単項演算子の実装を提供することもできます。単項演算子は 1 つのターゲットに作用します。ターゲットの前に置く (-a
のような) 場合は前置演算子で、ターゲットの後に置く (b!
のような) 場合は後置演算子です。
演算子関数を宣言するには、func
キーワードの前に prefix
または postfix
を記述して、前置単項演算子あるいは後置単項演算子を実装します。
prefix func - (vector: Vector2D) -> Vector2D {
return Vector2D(x: -vector.x, y: -vector.y)
}
この例では、Vector2D
インスタンスの単項マイナス演算子 (-a
) を実装しています。単項マイナス演算子は前置演算子であるため、この関数に prefix
を付ける必要があります。
単純な数値では、単項マイナス演算子は正の値を負の相当する値に変換し、逆の場合も同じようになります。Vector2D
インスタンスに対する実装では、x
プロパティと y
プロパティの両方に対してこの演算を実行します。
let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive
// negative は Vector2D インスタンスで、値は (-3.0, -4.0)
let alsoPositive = -negative
// alsoPositive は Vector2D インスタンスで、値は (3.0, 4.0)
複合代入演算子
複合代入演算子は、代入 (=
) と別の演算を組み合わせます。例えば、加算代入演算子 (+=
) は、加算と代入を組み合わせて 1 つの演算にします。パラメータの値が演算子関数内で直接変更されるため、複合代入演算子の入力パラメータ left
を inout
にします。
次の例では、Vector2D
インスタンスに対する加算代入演算子関数を実装しています。
func += (inout left: Vector2D, right: Vector2D) {
left = left + right
}
加算演算子は事前に定義しているため、ここでは加算処理を再実装する必要はありません。加算代入演算子関数は、既存の加算演算子関数を活かし、left
値と right
値を加算して left
の値に設定します。
var original = Vector2D(x: 1.0, y: 2.0)
let vectorToAdd = Vector2D(x: 3.0, y: 4.0)
original += vectorToAdd
// original の値は (4.0, 6.0)
=
) をオーバーロードすることはできません。複合代入演算子のみオーバーロードすることができます。同様に、三項演算子 (a ? b : c
) をオーバーロードすることもできません。
等価演算子
クラスと構造体は、「等しい」演算子 (==
) と「等しくない」演算子 (!=
) として知られる、等価演算子のデフォルト実装を受け取りません。「等しい」の意味が型の役割に依存するため、独自の型において何が「等しい」とみなせるのかを Swift が推測することはできません。
独自の型の等価性をチェックするために等価演算子を使用するには、他の中置演算子と同じように演算子の実装を提供します。
func == (left: Vector2D, right: Vector2D) -> Bool {
return (left.x == right.x) && (left.y == right.y)
}
func != (left: Vector2D, right: Vector2D) -> Bool {
return !(left == right)
}
この例では、2 つの Vector2D
インスタンスが等価の値であるかをチェックするために、「等しい」演算子 (==
) を実装しています。Vector2D
のコンテキストでは、両インスタンスの x
値と y
値が同じであることを「等しい」とみなすと意味をなすため、このロジックが演算子の実装で使用されています。また、この例では「等しくない」演算子 (!=
) を実装し、単に「等しい」演算子の結果の逆を返します。
2 つの Vector2D
インスタンスが等価であるかをチェックするために、これらの演算子を使用することができるようになります。
let twoThree = Vector2D(x: 2.0, y: 3.0)
let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
if twoThree == anotherTwoThree {
print("These two vectors are equivalent.")
}
// "These two vectors are equivalent." と出力
Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.