Що робить ключове слово "by" у Котліні?


Відповіді:


76

У посиланні на Kotlin ви знайдете два способи використання by, причому перше - делеговані властивості, тобто використання, яке ви використовували вище:

Існують певні загальні типи властивостей, які, хоча ми можемо реалізовувати їх вручну кожного разу, коли вони нам потрібні, було б дуже приємно впровадити раз і назавжди та помістити їх у бібліотеку. Приклади включають ледачі властивості: значення обчислюється лише при першому доступі, спостережувані властивості: слухачі отримують сповіщення про зміни в цій властивості, зберігаючи властивості на карті, а не в окремому полі.

Тут ви делегуєте getter / setter до іншого класу, який виконує роботу і може містити загальний код. В якості іншого прикладу, деякі інжектори залежностей для Kotlin підтримують цю модель, делегуючи геттер для отримання значення з реєстру екземплярів, керованих механізмом введення залежностей.

І передача інтерфейсу / класу - це інше використання:

Шаблон делегування виявився хорошою альтернативою успадкуванню реалізації, і Kotlin підтримує його, що вимагає від нуля типового коду. Клас Похідний може успадкувати від бази інтерфейсу та делегувати всі його загальнодоступні методи вказаному об'єкту

Тут ви можете делегувати інтерфейс іншій реалізації, тому виконуючому класу потрібно лише перевизначити те, що він хоче змінити, тоді як решта методів делегують назад до повнішої реалізації.

Живим прикладом може бути колекція Klutter Readonly / Immutable, де вони насправді просто делегують конкретний інтерфейс колекції іншому класу, а потім замінюють все, що має бути іншим у реалізації лише для читання. Заощаджуючи багато роботи, не потрібно вручну делегувати всі інші методи.

Обидва вони охоплені посиланням на мову Kotlin , починаючи з базових тем мови.


94

Простими словами, ви можете зрозуміти byключове слово, як це передбачено .

З точки зору споживача власності, valце те, що має getter (отримати), і varце те, що має getter і setter (get, set). Для кожного varвластивості існує за замовчуванням постачальник методів get і set, який нам не потрібно явно вказувати.

Але, використовуючи byключове слово, ви заявляєте, що цей геттер / геттер і сеттер надається деінде (тобто він був делегований). Це забезпечується з допомогою функції , яка приходить після by.

Отже, замість використання цього вбудованого методу get і set, ви делегуєте це завдання якійсь явній функції.

Одним з дуже поширених прикладів є by lazyвластивості для ледачого завантаження. Крім того, якщо ви використовуєте бібліотеку введення залежностей, як Koin, ви побачите багато властивостей, визначених таким чином:

var myRepository: MyRepository by inject()  //inject is a function from Koin

У визначенні класу він дотримується того самого принципу, він визначає, де надається якась функція, але він може посилатися на будь-який набір методів / властивостей, а не просто отримувати та встановлювати.

class MyClass: SomeInterface by SomeImplementation, SomeOtherInterface

Цей код говорить: «Я - клас MyClass, і я пропоную функції інтерфейсу SomeInterface, які надаються SomeImplementation. Я реалізую SomeOtherInterface самостійно (це неявно, тому ні by). '


23

введіть тут опис зображення

Синтаксис:

val/var <property name>: <Type> by <expression>. 

Вираз після by є делегатом

якщо ми намагаємося отримати доступ до значення властивості p , іншими словами, якщо ми викликаємо метод get () властивості p , викликається метод getValue () екземпляра делегата .

Якщо ми намагаємося встановити значення властивості p , іншими словами, якщо ми викликаємо метод set () властивості p , буде викликаний метод setValue () екземпляра делегата .


7

Делегування власності:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.