なんか 金は愛よりも重い - Qiita という悲しい話題を見てしまいましたが、 Kotlin ならそんな悲しい現実も覆すことができます。
Kotlin は Web ブラウザ上で簡単にコードを実行できるツールが公式から出されているので、それを使って問題のコードを実行してみましょう。
素晴らしい! Kotlin なら「愛」は「金」よりも重くなることが証明されました!
説明
上のコードは、スクロールで見えなくなっているところも合わせると次のようになっています。
fun main(args: Array<String>) {
println("'金' < '愛' = " + ("金" < '愛'))
println("'愛' < '金' = " + ("愛" < '金'))
}
operator fun String.compareTo(c: Char) = c.toString().compareTo(this)
はい、 String に compareTo() を生やして大小比較を逆転させています、ごめんなさい。
Kotlin には演算子オーバーロードがあり、 < は compareTo() メソッドの実行に置き換えられます。
また、 Kotlin には拡張関数という、既存のクラスにメソッドを追加できる(ように見える)仕組みが用意されています。
つまり、 String に比較結果を逆転させる compareTo() メソッドを拡張関数で追加すれば、上のようなあべこべの結果を出すことができます。
しかし、 String にはすでに compareTo(String) という String 同士で比較しあうメソッドが定義されています。
拡張関数で追加したメソッドと同じシグネチャのメソッドが既にクラスに存在する場合、そのメソッドを実行しても拡張関数の方は実行されず、オリジナルのメソッドが必ず実行されます。
fun main(args: Array<String>) {
println("'金' < '愛' = " + ("金" < "愛"))
println("'愛' < '金' = " + ("愛" < "金"))
}
operator fun String.compareTo(s: String) = s.compareTo(this)
'金' < '愛' = false
'愛' < '金' = true
ただ、拡張関数はオーバーロードは問題なく動きます。
そして、幸いにも? String には compareTo(Char) のメソッドは定義されていません。
そこで、 compareTo(Char) のメソッドを拡張関数で定義し、 String の "金" と Char の '愛' を比較することで、上のような結果を得ることができます。
以上、 Kotlin の拡張関数の間違った使い方でした。
