Android向けに開発しているときに、次のようなものに出くわすことがあります。
var someModel: someViewModel by notNullAndObservable { vm ->
...
}
by
キーワードの意味がわかりません。
回答:
でKotlin参照あなたがのために2つの用途を見つけるだろうby
、最初のもの委任プロパティあなたは上に持って使用することです。
特定の一般的な種類のプロパティがあります。これらは必要なときに手動で実装できますが、一度だけ実装してライブラリに入れると非常に便利です。例としては、レイジープロパティがあります。値は最初のアクセス時にのみ計算されます。監視可能なプロパティ:リスナーは、このプロパティの変更について通知を受け取り、プロパティをそれぞれ個別のフィールドではなくマップに保存します。
ここでは、ゲッター/セッターを、作業を実行し、共通のコードを含めることができる別のクラスに委任します。別の例として、Kotlinの依存性注入器の一部は、依存性注入エンジンによって管理されるインスタンスのレジストリから値を受け取るようにゲッターを委任することで、このモデルをサポートしています。
そして、インターフェース/クラスの委任は他の用途です:
委任パターンは、実装の継承に代わる優れた方法であることが証明されており、Kotlinは、ボイラープレートコードをゼロにする必要があるネイティブパターンをサポートしています。Derivedクラスは、インターフェイスBaseから継承し、そのすべてのパブリックメソッドを指定されたオブジェクトに委任できます。
ここで、インターフェイスを別の実装に委任できるため、実装クラスは変更したいものをオーバーライドするだけで済み、残りのメソッドはより完全な実装に委任されます。
実例は、Klutter Readonly / Immutableコレクションです。で、実際には特定のコレクションインターフェイスを別のクラスに委任し、読み取り専用の実装で異なる必要があるものをすべてオーバーライドします。他のすべてのメソッドを手動で委任する必要がないため、多くの作業を節約できます。
これらは両方ともKotlin言語リファレンスでカバーされており、言語の基本トピックから始めます。
簡単に言えば、によって提供されるby
キーワードを理解することができます。
不動産消費者の観点からは、val
ゲッター(get)var
を持つものであり、ゲッターとセッター(get、set)を持つものです。それぞれについてvar
プロパティに、明示的に指定する必要のないgetメソッドとsetメソッドのデフォルトプロバイダーがあります。
ただし、by
キーワードを使用する場合は、このgetter / getter&setterが他の場所で提供されている(つまり、委任されている)ことを示しています。の後に続く関数によって提供されby
ます。
したがって、この組み込みのgetメソッドとsetメソッドを使用する代わりに、そのジョブを明示的な関数に委任します。
非常に一般的な例の1つは、by lazy
遅延読み込みプロパティの場合です。また、Koinのような依存性注入ライブラリを使用している場合は、次のように定義された多くのプロパティが表示されます。
var myRepository: MyRepository by inject() //inject is a function from Koin
クラス定義では、同じ原則に従い、関数が提供される場所を定義しますが、getとsetだけでなく、メソッド/プロパティの任意のセットを参照できます。
class MyClass: SomeInterface by SomeImplementation, SomeOtherInterface
このコードは次のように言っています。 '私はクラスMyClassであり、SomeImplementationによって提供されるインターフェイスSomeInterfaceの関数を提供します。SomeOtherInterfaceを自分で実装します(これは暗黙的であるため、by
ありません)。
プロパティの委任:
import kotlin.reflect.KProperty
class Delegate {
// for get() method, ref - a reference to the object from
// which property is read. prop - property
operator fun getValue(ref: Any?, prop: KProperty<*>) = "textA"
// for set() method, 'v' stores the assigned value
operator fun setValue(ref: Any?, prop: KProperty<*>, v: String) {
println("value = $v")
}
}
object SampleBy {
var s: String by Delegate() // delegation for property
@JvmStatic fun main(args: Array<String>) {
println(s)
s = "textB"
}
}
結果:
textA
value = textB
クラスの委任:
interface BaseInterface {
val value: String
fun f()
}
class ClassA: BaseInterface {
override val value = "property from ClassA"
override fun f() { println("fun from ClassA") }
}
// The ClassB can implement the BaseInterface by delegating all public
// members from the ClassA.
class ClassB(classA: BaseInterface): BaseInterface by classA {}
object SampleBy {
@JvmStatic fun main(args: Array<String>) {
val classB = ClassB(ClassA())
println(classB.value)
classB.f()
}
}
結果:
property from ClassA
fun from ClassA
パラメータの委任:
// for val properties Map is used; for var MutableMap is used
class User(mapA: Map<String, Any?>, mapB: MutableMap<String, Any?>) {
val name: String by mapA
val age: Int by mapA
var address: String by mapB
var id: Long by mapB
}
object SampleBy {
@JvmStatic fun main(args: Array<String>) {
val user = User(mapOf("name" to "John", "age" to 30),
mutableMapOf("address" to "city, street", "id" to 5000L))
println("name: ${user.name}; age: ${user.age}; " +
"address: ${user.address}; id: ${user.id}")
}
}
結果:
name: John; age: 30; address: city, street; id: 5000