これは標準的な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()
したがって、これは および の汎用関数でありT
、R
最初の引数「レシーバー」は 型 でT
、2 番目のf
引数は を拡張する拡張関数 型 で、によって返されるT
型を返します。R
with
たとえば、次のように使用できます。
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
追加した:
つまり、唯一有効なのは、
f
T に対して定義された引数 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
が、コンテキストからレシーバーの型を推測できる場合にのみ機能します。