Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
演算子オーバーロード
Kotlinでは『operator』キーワードを使って、演算子(+, -, *, [], () など)を独自クラスで再定義できます。演算子オーバーロードにより直感的な記法でオブジェクトを操作できます。
構文
data class Point(val x: Int, val y: Int) {
// + 演算子のオーバーロード
operator fun plus(other: Point): Point = Point(x + other.x, y + other.y)
// - 演算子のオーバーロード
operator fun minus(other: Point): Point = Point(x - other.x, y - other.y)
// 単項マイナス
operator fun unaryMinus(): Point = Point(-x, -y)
}
演算子一覧
| 演算子 | 関数名 | 概要 |
|---|---|---|
| +a | unaryPlus() | 単項プラスです。 |
| -a | unaryMinus() | 単項マイナスです。 |
| a + b | plus(b) | 加算です。 |
| a - b | minus(b) | 減算です。 |
| a * b | times(b) | 乗算です。 |
| a / b | div(b) | 除算です。 |
| a % b | rem(b) | 剰余です。 |
| a[i] | get(i) | インデックスアクセスです。 |
| a[i] = v | set(i, v) | インデックス代入です。 |
| a() | invoke() | 関数呼び出しです。 |
| a in b | contains(a) | 包含チェックです。 |
| a..b | rangeTo(b) | 範囲生成です。 |
サンプルコード
data class Vector(val x: Double, val y: Double) {
operator fun plus(other: Vector) = Vector(x + other.x, y + other.y)
operator fun minus(other: Vector) = Vector(x - other.x, y - other.y)
operator fun times(scale: Double) = Vector(x * scale, y * scale)
operator fun unaryMinus() = Vector(-x, -y)
// invoke() でオブジェクトを関数のように呼べます。
operator fun invoke(): Double = Math.sqrt(x * x + y * y) // 大きさ
override fun toString() = "($x, $y)"
}
class Matrix2x2(val a: Double, val b: Double, val c: Double, val d: Double) {
// [] でアクセスできます(row, col は 0 始まり)。
operator fun get(row: Int, col: Int): Double = when {
row == 0 && col == 0 -> a
row == 0 && col == 1 -> b
row == 1 && col == 0 -> c
else -> d
}
}
fun main() {
val v1 = Vector(3.0, 4.0)
val v2 = Vector(1.0, 2.0)
println(v1 + v2) // (4.0, 6.0)
println(v1 - v2) // (2.0, 2.0)
println(v1 * 2.0) // (6.0, 8.0)
println(-v1) // (-3.0, -4.0)
println(v1()) // 5.0(大きさ: √(9+16))
val mat = Matrix2x2(1.0, 2.0, 3.0, 4.0)
println(mat[0, 0]) // 1.0
println(mat[1, 1]) // 4.0
}
概要
演算子オーバーロードは数値計算・座標・行列・複素数など、数学的な概念を扱うクラスで特に効果を発揮します。ただし、直感に反する使い方は混乱を招くため、意味が自明な場合にのみ使うことを推奨します。
『invoke()』をオーバーロードするとオブジェクトを関数のように呼び出せます。これはDSLやビルダーパターンに活用できます。
データクラスの機能はdata classを、クラスの継承はopen / overrideを参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。