1.基本的な定義
1.1高階関数とは何ですか
定義により、より高次の関数である値を返す引数または関数としてさらに機能します。
Kotlinでは、関数は、関数またはラムダ参照によって表すことができます。
したがって、任意の順序lambda
または関数参照の引数または戻り値としてlambda
関数機能、または両方が満たされているか、機能の参照は、高次関数です。
1.2ラムダ大会:
:機能に精通してKotlin、あなたが最初のコードラムダ式を読み取る必要があり、我々は最初のような規則の数は場所を知る必要があります
関数が唯一のパラメータとして機能し、使用しているとき、lambda
式を関数の対応するパラメータを省略することができるように括弧()
。
関数の最後のパラメータを使用すると、カッコ内にパラメータリストの外側に書かれた関数のパラメータのラムダ式を使用することができ、種類の関数です。
例如:
str.sumBy( { it.toInt } )
可以省略成
str.sumBy{ it.toInt }
Anko的Context扩展alert函数,可以注意到positiveButton方法第一个参数是text,
第二个参数是监听器lambda表达式,写在了参数列表圆括号外面。
alert("确定删除吗?","Alert") {
positiveButton("OK") { Log.i(TAG, "你点了确定按钮")}
negativeButton("Cancel") { Log.i(TAG, "你点了取消按钮") }
}.build().show()
Javaコードに対応する1.3関数型変数
Kotlinでは、変数の型があってもよい函数类型
、例えば、次のコードsum
の種類は可変であるInt类型
、predicate
変数である函数类型
ことを、この変数は関数を表します。
声明一个名字为sum的Int类型变量(这个sum变量的类型是Int)
var sum:Int
声明一个名字为predicate的函数类型变量(这个predicate变量的类型是函数)
predicate是一个以Char为参数,返回值为Boolean的函数。
var predicate: (Char) -> Boolean
声明一个以predicate函数为参数的函数(高阶函数),这个函数的返回类型是String
fun filter(predicate: (Char) -> Boolean) :String
让上面这个函数带上接受者,其实就是给String声明了一个扩展函数。
带上了接收者的函数,函数内部可以直接访问String的其他方法属性,相当于函数内部的this就是String
fun String.filter(predicate: (char) -> Boolean) :String
対応する形の参照があることKotlin Java関数ようKotlinと混合するJavaコードは、起動され、すなわちFunction
、参照Function1<P, R>
のみつのパラメータタイプはR.の戻り値Pの基準型であることを意味します
2.標準の高次機能
高次機能の2.1宣言
で宣言された標準的な高階関数Standard.kt
を含む文書、TODO
、run
、with
、apply
、also
、let
、takeIf
、takeUnless
、repeat
機能しています。
私たちは、次のような、同様の機能を対比して機能しますrun & with
、apply & also
、takeIf & takeUnless
、let & 扩展函数版本run
。
2.2ラン&機能付き
/**
* Calls the specified function [block] and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
/**
* Calls the specified function [block] with `this` value as its receiver and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
/**
* Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}
実行機能のバージョンは、1つの機能の拡張版であり、一つは仕様の通常バージョンである、2つのバージョンを持っている
、コード定義から分かるrun函数
とる引数(高階関数)としての機能リファレンスをちょうどこのコードのビットを呼び出す内、戻り値のブロックとブロックのコードブロック。
それは見つけることができるwith
とrun
返されますblock
(関数のリファレンス)の戻り値。
:どのような違い
の差が、その後、使用する前に空にし言い渡され、必要に応じて、実行拡張機能があることである扩展函数版本的run函数
よりも使いwith函数
など、エレガント:
// Yack!
with(webview.settings) {
this?.javaScriptEnabled = true
this?.databaseEnabled = true
}
// Nice.
webview.settings?.run {
javaScriptEnabled = true
databaseEnabled = true
}
それは見ることができます扩展函数版本的run函数
呼び出しが最初webview.settingsが空であるかどうかを判断することができ、または関数呼び出しのボディを入力しないでください前に。
2.3にも適用されます&
/**
* Calls the specified function [block] with `this` value as its receiver and returns `this` value.
*/
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
/**
* Calls the specified function [block] with `this` value as its argument and returns `this` value.
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}
apply
・also
最後に、受信機自体に戻りT
コードをより明確に、コードサイズを絞り込み連鎖呼び出しを実現することができる、それらの間の差が使用されている受信機としてので、内部にアクセスすることができ、それがパラメータとして渡されますその中に内部必要性の代理受信者。apply
block
T(也就是apply的接收者本身)
apply
block
T这个this
also
T
block
also
block
it(lambda的唯一参数)
also
T
上の使用:
一般的には、lambda
のためのパラメータit
の機能は、多くの場面を読んだとして使うのに適して、名前付きパラメータを使用することができますがされit
、コードの可読性を高めるために、適切な名前に変更しT
、着信block(T)
、書き込み値のための機会がより適切な繰り返し文州T変数がたくさんあるため。
主にあれば、ブロックラムダ式を[推奨]、インスタンスの書き込み、インスタンスが宣言されReceiver
、場合に主が読み出され、インスタンスは、パラメータを宣言しました。
だから、長いも、コードの読み取り動作の長いブロックを使用して、コードブロックライト動作値を適用します。
inline fun <T> T.apply(block: T.() -> Unit): T//对T进行写操作,优先使用apply
tvName.apply {
text = "Jacky"
textSize = 20f
}
inline fun <T> T.also(block: (T) -> Unit): T //对T进行读操作 优先使用also
user.also {
tvName.text = it.name
tvAge.text = it.age
}
2.4 Let関数
/**
* Calls the specified function [block] with `this` value as its receiver and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
/**
* Calls the specified function [block] with `this` value as its argument and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
let
この機能は、ある扩展版本的run函数
ような非常に多く、私は上記のコードとは対照的に入れて、両者の差がrun
あるblock参数
こと1 带run接收者T的函数引用
、およびにするパラメータとしてその差が呼び出しの使用であるので、、内部ポインティング、及びで内部の必要性を指すように、内部にはを参照する外部のあなたはのようなものを意味し、内部の使用、内部がこれです。let
block参数是
let的接收者T
block
run
block
this
T
let
block
it
T
let
block
this
T
this
Activity
let
let
block
this
Activity实例
run
関数が複数のコードブロックを記述するのに適した値を比較し、let
関数は、コードブロックをマルチ読み取るのに適しています。
2.4.1も差の戻り値を聞かせて
let
戻りblock的返回值
、also
戻り接收者T自身
、そう、彼らはチェーンを呼び出すには、本質的に異なっています。let
あなたは似て達成することができますRxJava
にmap
効果
val original = "abc"
// Evolve the value and send to the next chain
original.let {
println("The original String is $it") // "abc"
it.reversed() // evolve it as parameter to send to next let
}.let {
println("The reverse String is $it") // "cba"
it.length // can be evolve to other type
}.let {
println("The length of the String is $it") // 3
}
// Wrong
// Same value is sent in the chain (printed answer is wrong)
original.also {
println("The original String is $it") // "abc"
it.reversed() // even if we evolve it, it is useless
}.also {
println("The reverse String is ${it}") // "abc"
it.length // even if we evolve it, it is useless
}.also {
println("The length of the String is ${it}") // "abc"
}
// Corrected for also (i.e. manipulate as original string
// Same value is sent in the chain
original.also {
println("The original String is $it") // "abc"
}.also {
println("The reverse String is ${it.reversed()}") // "cba"
}.also {
println("The length of the String is ${it.length}") // 3
}
上記では、それはそうですT.also
、我々は簡単に一つの機能ブロックにそれらを組み合わせることができますので、無意味のように。しかし、それについて考える、それはいくつかの利点があります:
これは、同じオブジェクト上に設けることができる非常に明確な分離プロセス、すなわち、小さい機能部の製造。
使用前に、それは、非常に強力な自己操作を実現することができチェーン動作ビルダー(ビルダーモード)を達成します。
2.5 takeIf&takeUnless
/**
* Returns `this` value if it satisfies the given [predicate] or `null`, if it doesn't.
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (predicate(this)) this else null
}
/**
* Returns `this` value if it _does not_ satisfy the given [predicate] or `null`, if it does.
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (!predicate(this)) this else null
}
これら二つの機能は、条件判断を行うために使用される場合、使用されるtakeIf
ことがであるpredicate
返すように条件true
受信機自体が、これらのリターンかどう場合戻すためにnull
、takeUnless
反対が正確であるpredicate
ためにfalse
戻りそうでなければ、受信機自体を返しますnull
。
2.6リピート機能
/**
* Executes the given function [action] specified number of [times].
*
* A zero-based index of current iteration is passed as a parameter to [action].
*
* @sample samples.misc.ControlFlow.repeat
*/
@kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0 until times) {
action(index)
}
}
この機能は、することですaction
繰り返し実行ブロックtimes
、二度action
パラメータは、現在実行中であるindex
(何度も)。
2.7これまたパラメータ対
あなたがチェックするとT.run
関数のシグネチャを、あなたはそれに気づくでしょうT.run
ちょうど拡張関数呼び出しとしてblock: T.()
。したがって、すべての範囲は、T
と呼ばれてもよいですthis
。プログラミングでは、this
ほとんどの時間を省略することができます。したがって、上記の例では、我々は可能println
ステートメントを使用$length
代わりに${this.length}
。私は、転送呼び出しthis
パラメータを。
しかし、用T.let
関数のシグネチャ、あなたはそれがわかりますT.let
、パラメータとして自分自身の中に渡し、それがありますblock: (T)
。だから、それは渡すようなものだlambda
パラメータを。これは、範囲の範囲内で使用することができるit
基準となります。だから私は、転送呼び出しit
パラメータを。
上から見た、ように見えるT.run
ので、より優れていることT.let
がより隠されたが、これはあるT.let
いくつかの微妙な利点の機能は次のとおりです。
T.let
比較外部クラスの機能は/メンバーは、与えられた変数の関数は/メンバーは明確に区別提供
にthis
それが関数のパラメータとして渡される場合、例えば、ケースを省略することができないit
よりthis
短く、より明確。
ではT.let
、変数は、より良い名前を使用することができます、あなたは切り替えることができますit
別の名前に。
stringVariable?.let {
nonNullString ->
println("The non null string is $nonNullString")
}
これらの機能の2.8選択は、次のとおりです。
コールチェーンの元の型を保つ(T - > T) | 他のタイプへのコールチェーン(T - > R) | コールチェーン開始(考えます) | コールチェーンアプリケーション条件文 | |
---|---|---|---|---|
書き込み操作 | T.apply {...} | T.run {...} | (T){...}と | T.takeIf / T.takeUnless |
マルチリード | T.also {...} | T.let {...} |
3.高次機能をカスタマイズ
コード3.1デバッグ環境で実行する前に、
//声明:
inline fun debug(code: () -> Unit){
if (BuildConfig.DEBUG) {
code()
}
}
//用法:
fun onCreate(savedInstanceState: Bundle?) {
debug {
showDebugTools();
}
}
宣言された関数inline
はコンパイル時にインラインコードをコピーして、対応するローカルコールに貼り付けられます、大規模で複雑な関数本体あれば、それ以外の場合は、ボリュームの増加を詰めるだろう、インラインでの使用はお勧めしません。
4.アンコ関連の発表
4.1アンコギャラリーは、標準のダイアログボックスを表示します
alert("确定删除吗?","Alert") {
positiveButton("OK") { Log.i(TAG, "你点了确定按钮")}
negativeButton("Cancel") { Log.i(TAG, "你点了取消按钮") }
}.build().show()
4.2アンコライブラリは、いくつかの部分が含まれています。
アンコは、いくつかの部分で構成されています。
- アンココモンズ:ように意図、ダイアログ、ログおよびのためのヘルパーの完全な軽量ライブラリ。
- アンコレイアウト:ダイナミックAndroidのレイアウトを記述するための高速かつタイプセーフな方法。
- アンコのSQLite:AndroidのSQLiteのためのクエリDSLおよびパーサコレクション。
- アンココルーチン:[kotlinx.coroutines]に基づいて、ユーティリティ
公共の一部:テント、ダイアログ、ログおよび他の高階関数。
レイアウトセクション:動的な拡張機能は、迅速な表示された4.1標準のダイアログボックスとして、レイアウトを追加します。
SQLiteの部品:クエリの解析DSL用のセット
コルーチン部分:コルーチン関連ツール。
4.2.1アンコレイアウト(ウィキ)
アンコレイアウトは動的なAndroidのレイアウトを記述するためのDSLです。ここではアンコのDSLで書かれたシンプルなUIは以下のとおりです。
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
4.2.2アンコのSQLite(ウィキ)
あなたは今までAndroidのカーソルを使用してSQLiteのクエリ結果を解析するのに疲れていますか?アンコSQLiteは SQLiteのデータベースで作業を簡素化するためにヘルパーの多くを提供します。
たとえば、ここにあなたが特定の名前を持つユーザーの一覧を取得する方法です。
fun getUsers(db: ManagedSQLiteOpenHelper): List<User> = db.use {
db.select("Users")
.whereSimple("family_name = ?", "John")
.doExec()
.parseList(UserParser)
}
アンコホームでの詳細な表情
5.リソース
Kotlinの標準機能をマスターする:実行を、また、聞かせてと適用、と
函数掌握Kotlin标准を:実行、また、聞かせてと適用、と
アンコ:https://github.com/Kotlin/anko
ます。https://www.jianshu.com/p/92c7581ab042で再現