Kotlin: Delegate — коротко про головне 🍁

Alexander Khyzhun
6 min readMar 8, 2023

--

Що таке Delegate і Delegation?

Делегування — використання об’єктом іншого об’єкта для реалізації тих чи інших функцій. Це в якійсь мірі передача повноважень від одного класа до другого.

Тобто, в програмуванні делегування має такий самий сенс як і в реальному світі.

Наприклад, якщо ви будуєте будинок, то вам треба будувати, потім, фарбувати, потім робити, наприклад, утеплення, і так далі.
Ви можете це все робити самостійно, а можете знайти майствій і делегувати їм цю роботу.

Ви їм гроші і матеріали, а вони вам результат через якийсь час. Тут сенс аналогічний тільки вот з виконанням ІТ-задач.

Why do we need to use Delegates?

Давайте я спробую пояснити вам це на прикладі.

Припустімо, ми хочемо дозволити класу A мати якусь функціональність класу Б. Як цього можна досягти?

Якщо все публічне, то ми зможемо використати функціональність другого класа, але в реальному світі такого у вас точно не буде))

Як варіант — ми можемо використовувати наслідування: робимо один клас відкритим, другим наслідуємось від першого — вуаля, готово.

В такому випадку у нас буде статичний звʼязок між класами і ми зможемо використовувати батьківські функції в child класі, але звісно тільки ті, де модифікатор доступа це дозволяє зробити.

Цікаво, а чи можна зробити два незалежні класи, без наслідування, але зробити це таким чином, щоб один клас мав до функціональності другого?
— і відповідь ТАК. Це і буде делегування.

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

Цей факт робить делегування надзвичайно потужним механізмом.

Існує два види делегування:
1. Явне — Може бути реалізований будь-якою обєктно-орієнтованою мовою.
2. Неявне — Для цієї функції потрібна підтримка мови.

ЯВНЕ ДЕЛЕГУВАННЯ

Давайте на основі ось такого приклада подивимось як працює явне делегування.

Я вибрав приклад на Java, оскільки більшість людей буде його розуміти, так як більшість людей все-таки переходять з Java, а не вивчають Kotlin з нуля, але якщо раптом є і люди без знання Java, то нічого страшного в цьому немає, все досить зрозуміло і очевидно.

Глибинні знання Java не потрібні, тут головне просто зрозуміти сенс того, що і як робиться. Так ось:

class View {
void show() {
print(“
View.show()”);
}
}

class Screen {

private View view; // delegation link

public Screen(View view) {
this.view = view;
}

void show() {
view.show();
}
}

public static void main(String args[]) {
View view = new View();
// establish delegation between two objects
Screen screen = new Screen(view);
screen.show(); View.show()
}

Цей приклад досить простий і знову ж таки — зрозумілий приклад.

Тут явно передається клас View чим і заміняється власна реалізацю на делеговану. Звертаю вашу увагу на те, що ми не використовуємо ніяких “фіч” мови для делегування. Все це чисте “ООП”.

Явне делегування вимагає багато зусиль, щоб написати методи, які містять переадресацію викликів для делегованого екземпляра. Ось чому багато мов підтримують цю функцію одразу (з коробки).

Звідси ми логічно переходимо до наступної теми — НЕЯВНЕ ДЕЛЕГУВАННЯ

НЕЯВНЕ ДЕЛЕГУВАННЯ

Якщо мова програмування має функціональність делегування “з коробки”,
яка дозволяє об’єкту призначати інший обʼєкт як «батьківський», називається — неявним делегуванням.

Воно, зокрема, поділяється на “непередбачуване” та “передбачуване” делегування:

  • Випадок, коли структура делегування може змінюватися динамічно, називається непередбачене.
  • Тоді як другий тип відноситься до того, що об’єкт не може змінити батьківський протягом свого життєвого циклу.

Є багато мов, які мають цю функцію з коробки, як-от Kotlin. Він розроблений, щоб бути «кращою мовою», аніж Java, але при цьому взаємодіяти з нею.

Kotlin, на відміну від Java, підтримує делегування з “коробки” і у нього є 2-і форми делегування: це делегування класу та властивостей.

Делегування класу

interface Nameable {
val name: String
}

class Jack: Nameable {
override val name: String = “Jack”
}

class Person(name: Jack) : Nameable by name {
// override val name: String = “Jack” // not needed
}

fun main(args: Array<String>) {
val person = Person(name = Jack())
println(person.name) //Jack
}

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

5. Property Delegation
Давайте ще подивимось на делегування пропертєй.
Делегування протертей ділиться на 2 типи:
— Read and Write
— та Read Only

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

Давайте створемо з вами property і назвемо її upperCaseText, яка буде String-гою і давайте пропишемо їй наступий getter і setter:

getter — буде повертати наш String, але все буде UPPERCASE-ом
setter — буде вивотиди наш текст LOWERCASE-ом і призначати значення

var upperCaseText: String = “”
get() =
field.uppercase()
set(value) {
println(value.lowercase())
field = value
}

fun main() {
upperCaseText = “Putler Loh” // кожне слово з великої
println(upperCaseText)
}

Result:
> putler loh
> PUTLER LOH

Якщо у вас буде багато таких property, то у вас буде дублюватись логіка, яка знаходиться всередині get/set методів, що вочевидь — погано.

Щоб не дублювати логіку, як варіант, ви можете створити делегат, якому ви будете делегувати виконання певної логіки.

Ви можете винести її в окрему функції і просто перевикористовувати. Так, і ви будете цілком праві, воно буде нормально працювати і все у вас буде в житті добре.

Але так як тему відео саме делегати, то я покажу як вирішити таку проблеми використовуючи саме їм.

В програмуванні досить важливо вміти вирішувати певну проблема декількома шляхами, тому делегати як варіант дійсно можуть підійти для цього.

Давайте спробуємо створити наш власний делегат. При створені кастомних делегатів необхідно пам’ятати, що в нас є варіанта:

  • ReadOnlyProperty — на випадок, коли нам потрібно тільки зчитувати дані
  • ReadWriteProperty — на випадок, якщо нам потрібно і зчитувати, і змінювати значення

class TextDelegate : ReadWriteProperty<Any?, String> {
var text: String = “”

override fun getValue(
thisRef: Any?,
property: KProperty<*>
): String {
return text.
uppercase()
}

override fun setValue(
thisRef: Any?,
property: KProperty<*>, value: String
) {
text = value.
lowercase()
}

private fun example() {
//do something with non-formatted value
}
}

class MyDelegationClass {
var someText by TextDelegate()
}

fun main() {
val example = MyDelegationClass()
example.someText = “Putler Loh”
println(example.someText)
}

Висновки

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

Ми побачили, що шаблон делегування є потужним механізмом, і це велике задоволення, що Kotlin реалізує цю концепцію з коробки.

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

Сподіваюся, це матеріал був для вас корисним.
Дякую, що дійшли ло його закінчення.

🎬 Ось мій канал, де будуть всі відео на різні теми в програмуванні:

📚 Ось мій Patreon, де будуть всі матеріали в текстовому форматі, додаткова інфа, розбір приклдів, домашні завдання, ІТ-словник, і тд:

Окрім цього, там є різні пропозиції, наприклад, можемо займатись 1х1, можу допомогти зробити резюме, проведу співбесіду і так далі.

🎬 Весь контент, який я роблю — це все мій особистий досвід.
Я пишу/знімаю все сам і ділюсь з вами корисною інформацією, яку ніхто не розповідає, тому підтримайте підпискою ❤️

🙂 На цьому у мене — все!
👉🏻 Ставте лексуси, підписуйтесь і будьте умнічками.

Якщо я правий — похваліть, якщо ні — посваріть.
Но в любому випадку не забудьте дати фідбек 😉

Успіхів! 🇺🇦🦄

--

--

Alexander Khyzhun
Alexander Khyzhun

Written by Alexander Khyzhun

🧙🏻‍♂️ Software Wizard 🎬 Tech blogger 🎌 JDM 🎷 Lofi artist 🏊🏻‍♂️ Swimmer

No responses yet