Kotlinで試してみる

Kotlinのリソースで試す

1. 前書き

JVMを対象とする言語などの管理言語は、最も一般的なリソースであるメモリを自動的に処理します。

ただし、メモリだけでなく、ファイル、ネットワーク接続、ストリーム、ウィンドウなど、あらゆる種類のリソースを扱う必要があります。 そして、just like memory, those need to be released when no longer needed.

この記事では、Kotlinでリソースを自動的に管理する方法と、Java’s try-with-resources constructとの違いについて説明します。

理論をスキップしたい場合は、jump straight to the example

2. 自動リソース管理

Java(擬似コード)でリソースを操作する場合、3つの異なるフェーズを区別できます。

resource = acquireResource()
try {
    useResource(resource)
} finally {
    releaseResource(resource)
}

言語またはライブラリがリソース(finallyの部分)の解放を担当している場合、それをAutomatic Resource Management.と呼びます。このような機能relieves us from having to remember to free a resource.

また、リソース管理は通常ブロックスコープに関連付けられているため、複数のリソースを同時に処理する場合、それらは常に正しい順序でリリースされます。

Javaでは、リソースを保持し、自動リソース管理の対象となるオブジェクトは、特定のインターフェースを実装します。I/ O関連リソースの場合はCloseableAutoCloseableの場合です。

また、Java 7は、既存のCloseableインターフェースを改良して、AutoCloseableを拡張しました。

したがって、Kotlinには、リソースホルダーと同じ概念があります。つまり、CloseableまたはAutoCloseableのいずれかを実装するオブジェクトです。

3. Kotlinのuse関数

リソースを自動的に管理するために、一部の言語には専用の構造があります。たとえば、Java 7ではtry-with-resourcesが導入されていますが、C#ではthe using keywordが導入されています。

時々、RAII in C++のようなパターンを提供してくれます。 他の場合には、ライブラリメソッドを提供します。

Kotlinは後者のカテゴリに分類されます。

設計上、doesn’t have a language construct akin to try-with-resources in Java.

代わりに、標準ライブラリでuseという拡張メソッドを見つけることができます。

これについては後で詳しく説明します。 今のところ、すべてのリソースホルダーオブジェクトには、呼び出すことができるuseメソッドがあることを知っておく必要があります。

3.1. どうやって使うのですか

簡単な例:

val writer = FileWriter("test.txt")
writer.use {
    writer.write("something")
}

Javaのtry-with-resourcesの場合と同様に、AutoCloseableまたはCloseableを実装する任意のオブジェクトでuse関数を呼び出すことができます。

このメソッドはラムダ式を受け取り、それを実行し、通常または例外を除いて、実行がブロックを離れるたびに(close()を呼び出すことによって)のリソースを破棄します。

したがって、この場合、use,の後、Kotlinが自動的に閉じたため、writerは使用できなくなります。

3.2. 短い形式

上記の例では、わかりやすくするために、writerという変数を使用して、クロージャを作成しました。

ただし、useは、リソースを保持するオブジェクトの単一パラメーターを持つラムダ式を受け入れます。

FileWriter("test.txt")
  .use { w -> w.write("something") }

ブロック内では、暗黙の変数itを使用することもできます。

FileWriter("test.txt")
  .use { it.write("something") }

したがって、ご覧のとおり、オブジェクトに明示的な名前を付ける必要はありません。 ただし、過度に簡潔なコードを書くのではなく、明確にすることをお勧めします。

3.3. use()の定義

Kotlinの標準ライブラリにあるuse関数の定義を見てみましょう。

public inline fun  T.use(block: (T) -> R): R

<T : Closeable?, R>の部分で、use is defined as an extension function on Java’s Closeable interface.がわかります。

拡張メソッドの詳細については、our introductory articleを参照してください。

もちろん、the use function is documentedはKotlinの標準ライブラリの一部です。

3.4. CloseableAutoCloseable

前のセクションの例に注意を払うと、use関数シグネチャがCloseableインターフェイスでのみ定義されていることがわかります。 This is because Kotlin’s standard library targets Java 6.

7より前のJavaバージョンでは、AutoCloseableは存在せず、もちろん、Closeableはそれを拡張しませんでした。

実際には、AutoCloseableを実装するが、Closeableを実装しないクラスはまれです。 それでも、それらの1つに遭遇する可能性があります。

その場合、Java 7、8、または対象とするバージョンのKotlinの拡張機能への依存関係を追加するだけで済みます。


    org.jetbrains.kotlin
    kotlin-stdlib-jdk8

依存関係の最新バージョンはMaven Centralにあります。

これにより、AutoCloseableインターフェイスで定義された別のuse拡張関数が得られます。

public inline fun  T.use(block: (T) -> R): R

4. 結論

このチュートリアルでは、Kotlinの標準ライブラリの単純な拡張関数が、JVMに認識されているすべての種類のリソースを自動的に管理するために必要なすべてであることがわかりました。

これらすべての例とコードスニペットの実装はthe GitHub projectにあります。これはMavenプロジェクトであるため、そのままインポートして実行するのは簡単です。