T.() を使用した Kotlin 関数シグネチャはどういう意味ですか? 質問する

T.() を使用した Kotlin 関数シグネチャはどういう意味ですか? 質問する

これは標準的なKotlin関数です(私の知る限り)

inline fun<T> with(t: T, body: T.() -> Unit) { t.body() }

しかし、シグネチャが正確に何を意味するのか、簡単な英語で誰か書いていただけますか? これは、T の汎用関数で、最初の引数「t」は T 型、2 番目の「本体」は関数型で、???? の関数を受け入れて何も返しません (Unit)

Something.() -> Something という表記は、Anko などでかなり頻繁に使用されています。

inline fun Activity.coordinatorLayout(init: CoordinatorLayout.() -> Unit) = ankoView({ CoordinatorLayout(it) },init)

しかし、.() が何を意味するのかはどこにも説明されていなかったと思います...

ベストアンサー1

T.() -> Unit受信機付きの拡張機能型です。

Kotlin は通常の関数の他に、拡張関数をサポートしています。このような関数は、レシーバー型の指定がある点で通常の関数とは異なります。ここでは、それが汎用的なT.部分です。

拡張関数内のキーワードthisはレシーバーオブジェクト(ドットの前に渡されるもの)に対応するので、そのメソッドを直接呼び出すことができます(this親スコープからの参照は可能です)。修飾語付き)。


はい、関数はwith標準的なものです。現在のコードは次のとおりです。

/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#with).
 */
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()

したがって、これは および の汎用関数でありTR最初の引数「レシーバー」は 型 でT、2 番目のf引数は を拡張する拡張関数 型 で、によって返されるT型を返します。Rwith

たとえば、次のように使用できます。

val threadInfoString = with (Thread.currentThread()) {
    // isDaemon() & getPriority() are called with new property syntax for getters & setters
    "${getName()}[isDaemon=$isDaemon,priority=$priority]"
}


拡張機能のドキュメントについては、こちらをご覧ください:
kotlinlang.org/docs/reference/lambdas.html#拡張関数式
kotlinlang.org/docs/reference/scope-functions.html#with kotlinlang.org/docs/reference/extensions.html


追加した:

つまり、唯一有効なのは、fT に対して定義された引数 0 個の関数でしょうか?

そうでもない。Kotlinでは関数型と拡張関数型が統合されているなので、互換的に使用できます。たとえば、関数(String) -> Intが期待される場所に String::length を渡すことができます。

// map() expects `(String) -> Int`
// argument has type `String.() -> Int`
strings.map(String::length)

Thread.() -> String&のような型は(Thread) -> Stringバックグラウンド側からは同じです。実際、レシーバーは最初の引数です。

したがって、次の関数はいずれもThread.() -> String引数に適しています。

fun main(args: Array<String>) {
    val f1 = fun Thread.(): String = name
    val f2 = fun Thread.() = name
    val f3: Thread.() -> String = { name }
    val f4: (Thread) -> String = { it.name }
    val f5 = { t: Thread -> t.name }
    val f6: (Thread) -> String = Thread::getNameZ
    val f7: Thread.() -> String = Thread::getNameZ
    val f8 = Thread::getNameZ
}

fun Thread.getNameZ() = name

または、単に関数リテラル( {}) は の例と同じですthreadInfoStringが、コンテキストからレシーバーの型を推測できる場合にのみ機能します。

おすすめ記事