Kotlin 1.4.30 の新機能
Kotlin 1.4.30 では、新しい言語機能のプレビュー版が提供され、Kotlin/JVM コンパイラの新しい IR バックエンドがベータ版に昇格し、さまざまなパフォーマンスと機能の改善が導入されています。
新機能については、こちらのブログ記事でも詳しく説明されています。
言語機能
Kotlin 1.5.0 では、JVM レコードのサポート、シールドインターフェース、安定版インラインクラスといった新しい言語機能が導入される予定です。 Kotlin 1.4.30 では、これらの機能と改善点をプレビューモードで試すことができます。1.5.0 のリリース前に皆様からのフィードバックを反映できるよう、対応する YouTrack チケットでご意見をお聞かせいただけると幸いです。
これらの言語機能と改善点をプレビューモードで有効にするには、特定のコンパイラオプションを追加してオプトインする必要があります。 詳細は以下のセクションを参照してください。
新機能のプレビューについては、こちらのブログ記事で詳しく説明されています。
JVM レコードのサポート
JVM レコード機能は実験的 (Experimental) です。この機能は、将来廃止または変更される可能性があります。 オプトインが必要です (詳細は下記を参照)。評価目的でのみ使用してください。この機能に関するフィードバックを YouTrack でいただけると幸いです。
JDK 16 のリリースには、レコードと呼ばれる新しい Java クラス型を安定化する計画が含まれています。Kotlin のすべての利点を提供し、Java との相互運用性を維持するために、Kotlin は実験的なレコードクラスのサポートを導入しています。
Java で宣言されたレコードクラスは、Kotlin のプロパティを持つクラスと同様に利用できます。追加のステップは不要です。
1.4.30 以降、データクラスに @JvmRecord
アノテーションを使用することで、Kotlin でレコードクラスを宣言できるようになりました。
@JvmRecord
data class User(val name: String, val age: Int)
JVM レコードのプレビュー版を試すには、コンパイラオプション -Xjvm-enable-preview
と -language-version 1.5
を追加します。
JVM レコードのサポートについては引き続き作業を進めており、この YouTrack チケットを使用してフィードバックをお寄せいただけると幸いです。
実装、制限、構文に関する詳細は KEEP で確認できます。
シールドインターフェース
シールドインターフェースは実験的 (Experimental) です。これらは、将来廃止または変更される可能性があります。 オプトインが必要です (詳細は下記を参照)。評価目的でのみ使用してください。これらの機能に関するフィードバックを YouTrack でいただけると幸いです。
Kotlin 1.4.30 では、_シールドインターフェース_のプロトタイプが提供されます。これらはシールドクラスを補完し、より柔軟な制限されたクラス階層を構築することを可能にします。
これらは、同じモジュール外では実装できない「内部」インターフェースとして機能します。例えば、網羅的な when
式を記述する際に、この事実を利用できます。
sealed interface Polygon
class Rectangle(): Polygon
class Triangle(): Polygon
// when() is exhaustive: no other polygon implementations can appear
// after the module is compiled
fun draw(polygon: Polygon) = when (polygon) {
is Rectangle -> // ...
is Triangle -> // ...
}
別のユースケースとして、シールドインターフェースを使用すると、2つ以上のシールドスーパークラスからクラスを継承できます。
sealed interface Fillable {
fun fill()
}
sealed interface Polygon {
val vertices: List<Point>
}
class Rectangle(override val vertices: List<Point>): Fillable, Polygon {
override fun fill() { /*...*/ }
}
シールドインターフェースのプレビュー版を試すには、コンパイラオプション -language-version 1.5
を追加します。このバージョンに切り替えると、インターフェースに sealed
修飾子を使用できるようになります。この YouTrack チケットを使用してフィードバックをお寄せいただけると幸いです。
パッケージ全体のシールドクラス階層
シールドクラスのパッケージ全体の階層は実験的 (Experimental) です。これらは、将来廃止または変更される可能性があります。 オプトインが必要です (詳細は下記を参照)。評価目的でのみ使用してください。これらの機能に関するフィードバックを YouTrack でいただけると幸いです。
シールドクラスは、より柔軟な階層を形成できるようになりました。同じコンパイル単位および同じパッケージ内のすべてのファイルにサブクラスを持つことができます。以前は、すべてのサブクラスが同じファイル内に存在する必要がありました。
直接のサブクラスは、トップレベルであるか、任意の数の他の名前付きクラス、名前付きインターフェース、または名前付きオブジェクト内にネストされている場合があります。 シールドクラスのサブクラスは、適切に修飾された名前を持たなければなりません。ローカルオブジェクトや匿名オブジェクトにすることはできません。
シールドクラスのパッケージ全体の階層を試すには、コンパイラオプション -language-version 1.5
を追加します。この YouTrack チケットを使用してフィードバックをお寄せいただけると幸いです。
シールドクラスのパッケージ全体の階層について詳しくはこちら。
インラインクラスの改善
インライン値クラスはベータ版 (Beta) です。ほぼ安定していますが、将来的に移行手順が必要になる場合があります。変更を最小限に抑えるよう最善を尽くします。インラインクラス機能に関するフィードバックを YouTrack でいただけると幸いです。
Kotlin 1.4.30 では、インラインクラスがベータ版 (Beta) に昇格し、以下の機能と改善がもたらされました。
インラインクラスは値ベース (value-based) であるため、
value
修飾子を使用して定義できます。inline
とvalue
の修飾子は現在同等です。 将来の Kotlin バージョンでは、inline
修飾子を非推奨にする予定です。今後、JVM バックエンドの場合、クラス宣言の前に
@JvmInline
アノテーションが必須となります。kotlininline class Name(private val s: String) value class Name(private val s: String) // For JVM backends @JvmInline value class Name(private val s: String)
インラインクラスは
init
ブロックを持つことができます。クラスがインスタンス化された直後に実行されるコードを追加できます。kotlin@JvmInline value class Negative(val x: Int) { init { require(x < 0) { } } }
Java コードからインラインクラスを持つ関数を呼び出す: Kotlin 1.4.30 以前では、マングリングのため、インラインクラスを受け入れる関数を Java から呼び出すことはできませんでした。 今後は、マングリングを手動で無効にできます。Java コードからそのような関数を呼び出すには、関数宣言の前に
@JvmName
アノテーションを追加する必要があります。kotlininline class UInt(val x: Int) fun compute(x: Int) { } @JvmName("computeUInt") fun compute(x: UInt) { }
このリリースでは、不正確な動作を修正するために、関数のマングリングスキームを変更しました。これらの変更は ABI の変更につながりました。
1.4.30 以降、Kotlin コンパイラはデフォルトで新しいマングリングスキームを使用します。古い 1.4.0 のマングリングスキームを強制的に使用し、バイナリ互換性を維持するには、
-Xuse-14-inline-classes-mangling-scheme
コンパイラフラグを使用します。
Kotlin 1.4.30 ではインラインクラスがベータ版に昇格し、将来のリリースで安定版にする予定です。この YouTrack チケットを使用してフィードバックをお寄せいただけると幸いです。
インラインクラスのプレビュー版を試すには、コンパイラオプション -Xinline-classes
または -language-version 1.5
を追加します。
マングリングアルゴリズムに関する詳細は KEEP で確認できます。
Kotlin/JVM
JVM IR コンパイラバックエンドがベータ版に到達
Kotlin/JVM 用の IR ベースのコンパイラバックエンドは、1.4.0 でアルファ版 (Alpha) として発表されましたが、ベータ版に到達しました。これは、IR バックエンドが Kotlin/JVM コンパイラのデフォルトになる前の最後のプレ安定レベルです。
IR コンパイラによって生成されたバイナリの利用に関する制限を撤廃します。以前は、新しい JVM IR バックエンドでコンパイルされたコードは、新しいバックエンドを有効にした場合にのみ使用できました。1.4.30 以降、そのような制限はなくなり、新しいバックエンドを使用してライブラリなどのサードパーティ向けコンポーネントをビルドできます。新しいバックエンドのベータ版を試して、課題トラッカーでフィードバックをお寄せください。
新しい JVM IR バックエンドを有効にするには、プロジェクトの設定ファイルに以下の行を追加します。
Gradle の場合:
kotlintasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile::class) { kotlinOptions.useIR = true }
groovytasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) { kotlinOptions.useIR = true }
Maven の場合:
xml<configuration> <args> <arg>-Xuse-ir</arg> </args> </configuration>
JVM IR バックエンドがもたらす変更については、こちらのブログ記事で詳しく説明されています。
Kotlin/Native
パフォーマンスの改善
Kotlin/Native は 1.4.30 でさまざまなパフォーマンス改善が施され、コンパイル時間の短縮が実現しました。 例えば、Kotlin Multiplatform Mobile を使用したネットワークとデータストレージ サンプルのフレームワークをリビルドするのにかかる時間は、9.5 秒 (1.4.10) から 4.5 秒 (1.4.30) に短縮されました。
Apple watchOS 64ビットシミュレーターターゲット
x86 シミュレーターターゲットは watchOS バージョン 7.0 以降で非推奨となりました。最新の watchOS バージョンに対応するため、Kotlin/Native は 64ビットアーキテクチャでシミュレーターを実行するための新しいターゲット watchosX64
をサポートしました。
Xcode 12.2 ライブラリのサポート
Xcode 12.2 に同梱されている新しいライブラリのサポートを追加しました。Kotlin コードからこれらを使用できるようになりました。
Kotlin/JS
トップレベルプロパティの遅延初期化
トップレベルプロパティの遅延初期化は実験的 (Experimental) です。この機能は、将来廃止または変更される可能性があります。 オプトインが必要です (詳細は下記を参照)。評価目的でのみ使用してください。この機能に関するフィードバックを YouTrack でいただけると幸いです。
Kotlin/JS の IR バックエンドでは、トップレベルプロパティの遅延初期化のプロトタイプ実装が導入されています。これにより、アプリケーション起動時にすべてのトップレベルプロパティを初期化する必要が減り、アプリケーションの起動時間が大幅に改善されるはずです。
遅延初期化については引き続き作業を進めます。現在のプロトタイプをお試しいただき、この YouTrack チケット または公式の Kotlin Slack の #javascript
チャンネル (こちらから招待を取得) でご意見や結果を共有していただけると幸いです。
遅延初期化を使用するには、JS IR コンパイラでコードをコンパイルする際に -Xir-property-lazy-initialization
コンパイラオプションを追加します。
Gradle プロジェクトの改善
Gradle コンフィグレーションキャッシュのサポート
1.4.30 以降、Kotlin Gradle プラグインはコンフィグレーションキャッシュ機能をサポートします。これによりビルドプロセスが高速化されます。コマンドを実行すると、Gradle はコンフィグレーションフェーズを実行し、タスクグラフを計算します。Gradle はその結果をキャッシュし、その後のビルドで再利用します。
この機能を使用するには、Gradle コマンドを使用するか、IntelliJ ベースの IDE を設定します。
標準ライブラリ
テキストの大文字/小文字変換用ロケール非依存 API
ロケール非依存 API 機能は実験的 (Experimental) です。この機能は、将来廃止または変更される可能性があります。 評価目的でのみ使用してください。 この機能に関するフィードバックを YouTrack でいただけると幸いです。
このリリースでは、文字列と文字のケースを変更するための実験的なロケール非依存 API を導入します。 現在の toLowerCase()
、toUpperCase()
、capitalize()
、decapitalize()
API 関数はロケールに依存しています。 これは、異なるプラットフォームのロケール設定がコードの動作に影響を与える可能性があることを意味します。例えば、トルコ語ロケールでは、文字列「kotlin」が toUpperCase
を使用して変換されると、「KOTLIN」ではなく「KOTLİN」になります。
// current API
println("Needs to be capitalized".toUpperCase()) // NEEDS TO BE CAPITALIZED
// new API
println("Needs to be capitalized".uppercase()) // NEEDS TO BE CAPITALIZED
Kotlin 1.4.30 では、以下の代替手段が提供されます。
String
関数用:以前のバージョン 1.4.30 の代替 String.toUpperCase()
String.uppercase()
String.toLowerCase()
String.lowercase()
String.capitalize()
String.replaceFirstChar { it.uppercase() }
String.decapitalize()
String.replaceFirstChar { it.lowercase() }
Char
関数用:以前のバージョン 1.4.30 の代替 Char.toUpperCase()
Char.uppercaseChar(): Char
Char.uppercase(): String
Char.toLowerCase()
Char.lowercaseChar(): Char
Char.lowercase(): String
Char.toTitleCase()
Char.titlecaseChar(): Char
Char.titlecase(): String
Kotlin/JVM には、明示的な
Locale
パラメーターを持つオーバーロードされたuppercase()
、lowercase()
、titlecase()
関数もあります。
テキスト処理関数の変更点の完全なリストは KEEP で確認できます。
Char からコードへの変換、Char から数字への変換を明確化
Char
変換機能の明確な API は実験的 (Experimental) です。この機能は、将来廃止または変更される可能性があります。 評価目的でのみ使用してください。 この機能に関するフィードバックを YouTrack でいただけると幸いです。
現在の Char
から数値への変換関数は、異なる数値型で表現された UTF-16 コードを返しますが、これは文字列の数値表現を返す類似の String-to-Int 変換と混同されがちです。
"4".toInt() // returns 4
'4'.toInt() // returns 52
// and there was no common function that would return the numeric value 4 for Char '4'
この混同を避けるため、Char
の変換を、以下の2つの明確に命名された関数群に分離することを決定しました。
Char
の整数コードを取得する関数と、指定されたコードからChar
を構築する関数:kotlinfun Char(code: Int): Char fun Char(code: UShort): Char val Char.code: Int
Char
が表す数字の数値に変換する関数:kotlinfun Char.digitToInt(radix: Int): Int fun Char.digitToIntOrNull(radix: Int): Int?
Int
の拡張関数で、それが表す非負の1桁の数字を対応するChar
表現に変換します:kotlinfun Int.digitToChar(radix: Int): Char
詳細については KEEP で確認できます。
シリアライゼーションの更新
Kotlin 1.4.30 と共に、kotlinx.serialization
の 1.1.0-RC をリリースします。これにはいくつかの新機能が含まれています。
- インラインクラスのシリアライゼーションサポート
- 符号なしプリミティブ型のシリアライゼーションサポート
インラインクラスのシリアライゼーションサポート
Kotlin 1.4.30 以降、インラインクラスをシリアライズ可能にできます。
@Serializable
inline class Color(val rgb: Int)
この機能には、新しい 1.4.30 IR コンパイラが必要です。
シリアライゼーションフレームワークは、シリアライズ可能なインラインクラスが他のシリアライズ可能なクラスで使用される場合でも、ボックス化しません。
kotlinx.serialization
のドキュメントで詳しく説明されています。
符号なしプリミティブ型のシリアライゼーションサポート
1.4.30 以降、kotlinx.serialization の標準 JSON シリアライザを、UInt
、ULong
、UByte
、UShort
などの符号なしプリミティブ型に使用できるようになりました。
@Serializable
class Counter(val counted: UByte, val description: String)
fun main() {
val counted = 239.toUByte()
println(Json.encodeToString(Counter(counted, "tries")))
}
kotlinx.serialization
のドキュメントで詳しく説明されています。