Kotlinを学んでいると、この書き方はどこまで許されるんだろう? と思うことが頻繁にあるので色々試してみました。
全体を通して思いましたが、文法エラーの際のメッセージがやたら親切です。
基本
int型のrangeはintRangeだが、String型のrangeはClosedRange
- Javaとの互換性に関係がある?
val rng = 1..99
println(rng.javaClass.kotlin)
val strrng = "a".."z"
println(rng.javaClass.kotlin)
関数
関数の引数は再代入不可
- Classではコンストラクタの引数に
val
var
を指定できるが、関数の引数は常に不変 - あえて
var
を指定して再代入しようとしたが、そもそも修飾できない(できたとしてもすべきでないが)
fun sayHello(var word: String) { // var on parameter function is not allowed
word = "Hello"
println(word)
}
関数でジェネリクスを利用するときは、型名が関数名の前に来る
- クラスではクラス名の後に来るので宣言の仕方が異なることになる
- あえて関数名の後ろで宣言しようとすると当然文法エラーになる
fun generateContainer<E>(vararg elements: E) = Containers(*elements) // type parameter must be placed before the function name
メソッドをcallable referenceで参照すると、第一引数に自身のインスタンスをとる
- Pythonでメソッドの第一引数にselfを要求するようなイメージか
- どのような状況で使うのかよくわからない。
infix
などと組み合わせると良いのか?
val len = String::length
println(len("I love Kotlin."))
クラス・オブジェクト
通常のクラスはクラスヘッダーを省略できるが、data classでは省略できない
- 固定値だけのdata classを作るのであれば省略しても良さそうなものだが、それはenumを使えということか
data class Member { // Data class must have at least one primary constructor parameter
val id: Int = 0
val nickname: String = "hiro"
}
objectはコンストラクタを持てない
- インスタンスを作成することがないので納得
- したがって、data objectのような概念も存在しない
object Constants(val status_ok){} // Constructors are not allowed to object
data object Constants(val status_ok){} // Modifier data is not applicable for objects
コンパニオンオブジェクトはクラスに一つしか持てない
- もしもコンパニオンオブジェクトを使いまわせる仕様なら不便だったかもしれないが、単にJavaのStaticに代わるものだと考えれば納得
class ClassCompany() {
companion object Companion1 {}
companion object Companion2 {} // Only one companion object is allowed per class
}
Null許容型からはコンパニオンオブジェクトにアクセスできない
- 割とどっちでもいいが、なんとなく理由は気になる
class Car(val name: String) {
companion object Companion {}
}
fun main(vararg args: String) {
Car?.Companion // Unresolved reference: companion
}
抽象クラスの実装をデリゲートで省略することはできない
- インターフェースの実装をデリゲートするのみ可能
- デリゲートパターンで処理を拡張したくなるクラスはインターフェースを用意すべき?
(抽象クラスとインターフェースの一般的な使い分けがわからないのでなんとも言えない)
abstract class AbGreet() {
open fun hello() {
println("hello")
}
open fun bye() {
println("bye")
}
}
class ImplGreet() : AbGreet() {
override fun hello() {
println("HELLO!")
}
override fun bye() {
println("BYE!!!")
}
}
class Impl2Greet(val greet: ImplGreet) : AbGreet by greet {} // only interface can be delegated to