0Pricing
Kotlin Academy · レッスン

ベストプラクティス

直感的な演算子を保ちます

「ベストプラクティス」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。

演算子を直感的に保つ

演算子は、その意味が明白な場合にのみオーバーロードしてください。ベクトルに対する + は明確ですが、メール送信を意味する + は明確ではありません。

data class Vec(val x: Int, val y: Int) {
    operator fun plus(o: Vec) = Vec(x + o.x, y + o.y)
}

fun main() {
    println(Vec(1, 2) + Vec(3, 4))
}

期待される意味を保つ

通常の代数的な性質に従ってください。a + b は、対称的な型では交換可能であると感じられ、読者を驚かせない動作にするべきです。

data class Money(val cents: Int) {
    operator fun plus(o: Money) = Money(cents + o.cents)
}

fun main() {
    println(Money(100) + Money(50))
}

イミュータビリティを優先する

plus のような演算子は、レシーバーを変更するのではなく新しい値を返すようにしてください。これは数値の動作とも一致します。

data class Point(val x: Int) {
    operator fun plus(o: Point) = Point(x + o.x)
}

fun main() {
    val a = Point(1)
    val b = a + Point(2)
    println("${a.x} ${b.x}")
}

plus と plusAssign

イミュータブルな値には plus を定義し、ミュータブルなコンテナーをその場で変更する場合には plusAssign を定義してください。動作が競合する両方の演算子を定義することは避けてください。

class Cart {
    val items = mutableListOf<String>()
    operator fun plusAssign(item: String) { items.add(item) }
}

fun main() {
    val c = Cart()
    c += "book"
    println(c.items)
}

戻り値の型を合わせる

二項演算子からは同じ型を返し、結果を自然に連鎖できるようにしてください。

data class N(val v: Int) {
    operator fun plus(o: N) = N(v + o.v)
}

fun main() {
    println((N(1) + N(2) + N(3)).v)
}

巧妙さのためにオーバーロードしない

名前付き関数のほうが読みやすい場合は、そちらを使用してください。演算子は、本当に数値やコンテナーに似た意味を表す場合に使うものであり、パズルのような表現に使うものではありません。

data class Log(val lines: List<String>) {
    fun append(line: String) = Log(lines + line)
}

fun main() {
    println(Log(emptyList()).append("start").lines)
}

equals と hashCode の整合性を保つ

比較や等価性をオーバーロードする場合は、壊れたコレクションを作らないように equals と hashCode の整合性を保ってください。

data class Id(val v: Int)

fun main() {
    val set = hashSetOf(Id(1), Id(1))
    println(set.size)
}

演算子の優先順位に注意する

オーバーロードした演算子にも組み込み演算子と同じ優先順位が適用されます。自然な優先順位で期待どおりの結果になるように設計してください。

data class N(val v: Int) {
    operator fun plus(o: N) = N(v + o.v)
    operator fun times(o: N) = N(v * o.v)
}

fun main() {
    println((N(2) + N(3) * N(4)).v)
}

意外な演算子を文書化する

演算子が明らかでない動作をする場合は、呼び出し側が誤解しないようにコメントまたは KDoc を追加してください。

data class Range2(val start: Int, val end: Int) {
    // contains: is value inside the range?
    operator fun contains(v: Int) = v in start..end
}

fun main() {
    println(5 in Range2(1, 10))
}

in には contains を使用する

in 演算子は contains に対応します。所属関係が型に対して明確に定義できる場合にのみ、これをオーバーライドしてください。

class Team(val members: List<String>) {
    operator fun contains(name: String) = name in members
}

fun main() {
    val t = Team(listOf("Ann", "Bo"))
    println("Ann" in t)
}

迷ったら関数を使用する

明確な名前を持つメソッドは、ほとんどの場合、分かりにくい演算子より安全です。オーバーロードは、可読性が本当に向上する場合に限って使用してください。

data class Temperature(val c: Int) {
    fun warmerThan(o: Temperature) = c > o.c
}

fun main() {
    println(Temperature(30).warmerThan(Temperature(20)))
}

理解度チェック

演算子オーバーロードのベストプラクティスについての理解度を確認しましょう。

まとめ

演算子オーバーロードのベストプラクティスについて学びました。

  • 意味が明白で慣例に沿っている場合にのみオーバーロードします。
  • イミュータブルな値と同じ型の戻り値を優先し、結果を連鎖できるようにします。
  • plus(値)と plusAssign(変更)を分けます。
  • equals と hashCode の整合性を保ち、より明確になる場合は名前付き関数を優先します。
data class V(val x: Int) {
    operator fun plus(o: V) = V(x + o.x)
}

fun main() {
    println((V(2) + V(5)).x)
}

よくある質問

「ベストプラクティス」レッスンは無料ですか?

はい。「ベストプラクティス」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。

「ベストプラクティス」で何を学びますか?

直感的な演算子を保ちます ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Kotlin Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「ベストプラクティス」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このKotlin Academyレッスンでコードを書いて実行できますか?

はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 演算子関数
  2. 比較演算子
  3. インデックスとInvoke
  4. ベストプラクティス
← Kotlin Academyに戻る