Π’ΡƒΡ‚ΠΎΡ€ΠΈΠ°Π»Ρ‹
16 сСнтября 2021
Π’ΡƒΡ‚ΠΎΡ€ΠΈΠ°Π»Ρ‹
16 сСнтября 2021
ИспользованиС ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ Π² Kotlin

Π£Π·Π½Π°ΠΉΡ‚Π΅, ΠΊΠ°ΠΊ композиция Π΄Π΅Π»Π°Π΅Ρ‚ ваш ΠΊΠΎΠ΄ Π½Π° Kotlin Π±ΠΎΠ»Π΅Π΅ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ ΠΈ простым Π² обслуТивании.

ΠžΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅Β (ООП) Π²Π²ΠΎΠ΄ΠΈΡ‚ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ, ΡΠΏΠΎΡΠΎΠ±ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎΠΌΡƒ использованию ΠΈ открытости ΠΊΠΎΠ΄Π°, Π·Π°Ρ‰ΠΈΡ‚Π΅ ΠΎΡ‚ нСпрСдусмотрСнных ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ/состояний ΠΈ ΡΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΡŽ цСлостности Π΄Π°Π½Π½Ρ‹Ρ…, позволяя ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌ ΠΌΠΎΠ΄Π΅Π»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ сущности. Но ΠΏΡ€ΠΈ Π½Π΅ΠΏΡ€Π΅Π΄Π½Π°ΠΌΠ΅Ρ€Π΅Π½Π½ΠΎΠΌ использовании эти ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄Π΅Π»Π°ΡŽΡ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠΉ ΠΈΠ· самых популярных ΠΏΠ°Ρ€Π°Π΄ΠΈΠ³ΠΌ программирования, Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ обСспСчСниС уязвимым ΠΈ Ρ‚Ρ€ΡƒΠ΄Π½Ρ‹ΠΌ Π² обслуТивании.

ООП просто прСдоставляСт ΠΈΠ½Π³Ρ€Π΅Π΄ΠΈΠ΅Π½Ρ‚Ρ‹ - Π²Π°ΠΌ Ρ€Π΅ΡˆΠ°Ρ‚ΡŒ ΠΊΠ°ΠΊ ΠΈΡ… ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΊΠ°ΠΊ Β«Π³ΠΎΡ‚ΠΎΠ²ΠΈΡ‚ΡŒΒ» Ρ…ΠΎΡ€ΠΎΡˆΠ΅Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ обСспСчСниС.Β ΠŸΠΎΠΌΠ½ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎ основная Ρ†Π΅Π½Π½ΠΎΡΡ‚ΡŒ ПО состоит Π² возмоТности ΡΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ внСсСнию ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€ΡΡŽΡ‰ΠΈΡ… трСбования ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ, Π½Π° протяТСнии всСго срока слуТбы.Β ΠŸΡ€ΠΈ этом эффСктивноС ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€Π΅Π½ΠΈΠ΅ тСкущих потрСбностСй ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ являСтся Π²Ρ‚ΠΎΡ€ΠΈΡ‡Π½ΠΎΠΉ Ρ†Π΅Π½Π½ΠΎΡΡ‚ΡŒΡŽ.Β Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΡ€Π³Π°Π½ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ классы Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ вашС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ обСспСчСниС Π±Ρ‹Π»ΠΎ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ ΠΈ Π² дальнСйшСм.

НаслСдованиС и композиция - это ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ для установлСния ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠΉ ΠΌΠ΅ΠΆΠ΄Ρƒ классами ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ.Β Π’Π°ΠΆΠ½ΠΎ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ‚ΡŒ, ΠΊΠ°ΠΊΠΎΠΌΡƒ ΠΈΠ· Π½ΠΈΡ… ΠΎΡ‚Π΄Π°Ρ‚ΡŒ ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚Π΅Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ…ΠΎΡ€ΠΎΡˆΠΎ спроСктированноС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ обСспСчСниС.

Π’ этом Ρ‚ΡƒΡ‚ΠΎΡ€ΠΈΠ°Π»Π΅ Π²Ρ‹:

  • Π Π°Π·Π±Π΅Ρ€Π΅Ρ‚Π΅ΡΡŒ Π² наслСдовании ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ;
  • ΠŸΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄, основанный Π½Π° наслСдовании, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΈΡΠ°Ρ‚ΡŒ классы, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅ ΠΎΠ± ΠΈΡ… нСдостатках;
  • Π˜Π·ΡƒΡ‡ΠΈΡ‚Π΅ ΡˆΠ°Π±Π»ΠΎΠ½Ρ‹ дСлСгирования;
  • ΠŸΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ для Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³Π° классов Π½Π° основС наслСдования;
  • Π£Π·Π½Π°Π΅Ρ‚Π΅ ΠΎ by, ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠΌ словС Π²Β Kotlin.

Π’ процСссС Π²Ρ‹ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡ‚Π΅ΡΡŒ с Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ классов ΠΈ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅, ΠΊΠ°ΠΊ Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΡ… Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ.

ΠŸΡ€ΠΈΡˆΠ»ΠΎ врСмя Π³ΠΎΡ‚ΠΎΠ²ΠΈΡ‚ΡŒ!

ΠŸΡ€ΠΈΡΡ‚ΡƒΠΏΠ°Π΅ΠΌ ΠΊ Ρ€Π°Π±ΠΎΡ‚Π΅

Π‘ΠΊΠ°Ρ‡Π°ΠΉΡ‚Π΅ стартовый ΠΏΡ€ΠΎΠ΅ΠΊΡ‚. ЗапуститС IntelliJ IDEA ΠΈ Π²Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅Β Open….Β Π—Π°Ρ‚Π΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΉΠ΄ΠΈΡ‚Π΅ Π² ΠΏΠ°ΠΏΠΊΡƒ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈ ΠΎΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ Π΅Π΅.

Π’Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅ классы, сгруппированныС ΠΏΠΎ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ ΠΏΠ°ΠΊΠ΅Ρ‚Π°ΠΌ. Для удобства эти ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΈΠΌΠ΅ΡŽΡ‚ названия, основанныС Π½Π° Ρ€Π°Π·Π΄Π΅Π»Π°Ρ… Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ‚ΡƒΡ‚ΠΎΡ€ΠΈΠ°Π»Π°.

Β 

ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ содСрТит Ρ„Π°ΠΉΠ»Ρ‹ *Demo.kt с Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ΠΌ main(). Бамая ваТная Π²Π΅Ρ‰ΡŒ, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ слСдуСт ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, - это Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ содСрТит мноТСство ΠΏΠ»ΠΎΡ…ΠΎ спроСктированных классов, поэтому Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π΅Π³ΠΎ ΠΊΠ°ΠΊ Β«Π²Π΄ΠΎΡ…Π½ΠΎΠ²Π΅Π½ΠΈΠ΅Β» - Π²Ρ‹ Π±ΡƒΠ΄Π΅Ρ‚Π΅ ΠΈΡ… Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΡ‚ΡŒ ΠΏΠΎ ΠΌΠ΅Ρ€Π΅ продвиТСния.

НаслСдованиС

НаслСдованиС устанавливаСт Β«is-aΒ» ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρƒ классами.Β Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ класс наслСдуСт всС non-private поля ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ своСго Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ класса.Β Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Ρ‡Π΅Π³ΠΎ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ класс Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌ.

// 1
abstract class Pizza() {
  abstract fun prepare()
}

// 2
class CheesePizza() : Pizza() {
  override fun prepare() {
    println("Prepared a Cheese Pizza")
  }
}

class VeggiePizza() : Pizza() {
  override fun prepare() {
    println("Prepared a Veggie Pizza")
  }
}

fun main() {
  // 3
  val cheesePizza: Pizza = CheesePizza()
  val veggiePizza: Pizza = VeggiePizza()
  val menu = listOf(cheesePizza, veggiePizza)
  for (pizza in menu) {
    // 4
    pizza.prepare()
  }
}

Если Π²Ρ‹ собСрСтС ΠΈ запуститС этот Ρ„Π°ΠΉΠ», Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚:

Prepared a Cheese Pizza
Prepared a Veggie Pizza

Π˜Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎ здСсь происходит?

  1. Π£ вас Π΅ΡΡ‚ΡŒ абстрактный класс Pizza, содСрТащий prepare().
  2. CheesePizza ΠΈ VeggiePizzaΒ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌΠΈ классами Pizza.
  3. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ класс являСтся Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΌ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ CheesePizzaΒ ΠΈΠ»ΠΈ VeggiePizzaΒ Π² любом мСстС, Π³Π΄Π΅ Π²Π°ΠΌ Π½ΡƒΠΆΠ΅Π½ Pizza.
  4. Π”Π°ΠΆΠ΅ Ссли cheesePizzaΒ ΠΈ veggiePizza приводят ΠΊ Ρ‚ΠΈΠΏΡƒ Pizza, prepare()Β Π²Ρ‹Π·ΠΎΠ²Π΅Ρ‚ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΌΡƒ Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅ΠΌΡƒ классу, дСмонстрируя ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„Π½ΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅. Π­Ρ‚ΠΎ связано с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Pizza опрСдСляСт ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ имССтся ссылка, опрСдСляСт Ρ„Π°ΠΊΡ‚ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ.

Π—Π°ΠΌΠ΅Ρ‚ΠΊΠ°

Π―Π²Π»Π΅Π½ΠΈΠ΅, ΠΊΠΎΠ³Π΄Π° ΠΎΠ΄ΠΈΠ½ класс Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ Π΄Ρ€ΡƒΠ³ΠΎΠΉ, Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ наслСдованиСм Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ. Π”Ρ€ΡƒΠ³ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΠΎΠΉ наслСдования являСтся наслСдованиС интСрфСйса, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ интСрфСйс ΠΈΠ»ΠΈ класс Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ ΠΈΠ»ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ Π΄Ρ€ΡƒΠ³ΠΎΠΉ интСрфСйс. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ интСрфСйсы Π½Π΅ связаны с дСталями Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, ΠΏΡ€ΠΈ наслСдовании интСрфСйсов Π½Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Ρ‚ΠΎΠΉ ΠΆΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, Ρ‡Ρ‚ΠΎ ΠΈ ΠΏΡ€ΠΈ наслСдованиС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

Π‘ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΠ³ΠΎ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒΒ Π½Π΅ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ доступныС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹Β Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ класса Π² Π΅Π³ΠΎ Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅ΠΌ классС. Но Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡƒΠ±Π΅Π΄ΠΈΡ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ Π²Π·Π°ΠΈΠΌΠΎΠ·Π°ΠΌΠ΅Π½ΡΠ΅ΠΌΠΎΡΡ‚ΡŒ, ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°Π΅ΠΌΡƒΡŽΒ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΎΠΌ подстановки Π‘Π°Ρ€Π±Π°Ρ€Ρ‹ Лисков (LSP), ΠΎ Ρ‡Π΅ΠΌΒ Π²Ρ‹ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅.

ΠŸΡ€ΠΈΠ½Ρ†ΠΈΠΏ подстановки Π‘Π°Ρ€Π±Π°Ρ€Ρ‹ Лисков

Π‘ΡƒΡ‚ΡŒ LSP Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ подклассы Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π·Π°ΠΌΠ΅Π½ΡΡ‚ΡŒ свои супСрклассы. И для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ это ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ, ΠΊΠΎΠ½Ρ‚Ρ€Π°ΠΊΡ‚Ρ‹, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ супСрклассом, Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Π΅Π³ΠΎ подклассами.Β Π’Π°ΠΊΠΈΠ΅ ΠΊΠΎΠ½Ρ‚Ρ€Π°ΠΊΡ‚Ρ‹, ΠΊΠ°ΠΊ сигнатуры Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ (имя Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ Ρ‚ΠΈΠΏΡ‹ ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹), Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ ошибки Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ компиляции статичСски Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌΠΈ языками, Ρ‚Π°ΠΊΠΈΠΌΠΈ, ΠΊΠ°ΠΊ Java ΠΈ Kotlin.

Однако Ρ‚Π°ΠΊΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠ°ΠΊ бСзоговорочная Π²Ρ‹Π΄Π°Ρ‡Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, UnsupportedOperationException, Π² ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ…, ΠΊΠΎΠ³Π΄Π° это Π½Π΅ оТидаСтся Π² супСрклассС, Π½Π°Ρ€ΡƒΡˆΠ°ΡŽΡ‚ этот ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ.

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ, Π½Π°Ρ€ΡƒΡˆΠ°Π΅Ρ‚ Π»ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ LSP Π² Π½ΠΎΠ²ΠΎΠΌ ΠΈΠ»ΠΈ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΌ подклассС, посмотрСв, Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π»ΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π²Ρ‹Π·ΠΎΠ² Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° находился Π² Ρ‚Π΅Π»Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° if, Π΄Π°Π±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ, слСдуСт Π»ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΈΠ»ΠΈ Π½Π΅Ρ‚, Π² зависимости ΠΎΡ‚ Π½ΠΎΠ²ΠΎΠ³ΠΎ Π²Π²Π΅Π΄Π΅Π½Π½ΠΎΠ³ΠΎ подкласса, Ρ‚.Π΅. выполняСтся ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° is.

РСализация Π°Π½Ρ‚ΠΈΠΏΠ°Ρ‚Ρ‚Π΅Ρ€Π½ΠΎΠ² наслСдования

НаслСдованиС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ слуТит ΠΌΠΎΡ‰Π½Ρ‹ΠΌ способом достиТСния ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠ³ΠΎ использования ΠΊΠΎΠ΄Π°, Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ сцСнария. ИспользованиС наслСдования Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΌ, Π³Π΄Π΅ это нСумСстно, ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с обслуТиваниСм.Β Π’Ρ‹ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅ ΠΎΠ± этом Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… Ρ€Π°Π·Π΄Π΅Π»Π°Ρ….

НаслСдованиС ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠ³ΠΎ класса

Π―Π·Ρ‹ΠΊΠΈ Java Virtual Machine, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ Kotlin ΠΈ Java, Π½Π΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ классу Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ Π±ΠΎΠ»Π΅Π΅, Ρ‡Π΅ΠΌ ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ класса.

РаспакуйтС пакСт userservice. Он содСрТит Π΄Π²Π° класса обслуТивания: UserCacheService, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ…Ρ€Π°Π½ΠΈΡ‚ записи User Π² структурС Π΄Π°Π½Π½Ρ‹Ρ… Π² памяти, ΠΈ UserApiService, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΠΌΠ΅Π΅Ρ‚ Π·Π°Π΄Π΅Ρ€ΠΆΠΊΡƒ для модСлирования сСтСвого Π²Ρ‹Π·ΠΎΠ²Π°. На UserMediatorΒ ΠΏΠΎΠΊΠ° Π½Π΅Β ΠΎΠ±Ρ€Π°Ρ‰Π°ΠΉΡ‚Π΅ внимания.

ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ с UserCacheServiceΒ ΠΈ UserApiService для получСния записи User. Π’Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡƒΡΠΊΠΎΡ€ΠΈΡ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, поэтому сначала ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚ поиск ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ Π² UserCacheServiceΒ ΠΈ Π²Ρ‹Π²ΠΎΠ΄ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° поиска, Ссли ΠΎΠ½ сущСствуСт. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΌΠ΅Π΄Π»Π΅Π½Π½Ρ‹ΠΉ «сСтСвой» Π²Ρ‹Π·ΠΎΠ². Когда UserApiServiceΒ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ User, Π²Ρ‹ сохраняСтС Π΅Π³ΠΎ Π² кэшС для использования Π² Π±ΡƒΠ΄ΡƒΡ‰Π΅ΠΌ.Β ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π»ΠΈ Π²Ρ‹ ΡΠΌΠΎΠ΄Π΅Π»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ это, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ наслСдованиС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ?

// Error: Only one class may appear in a supertype list
/**
 * Mediates repository between cache and server. 
 * In case of cache hit, it returns the data from the cache;
 * else it fetches the data from API and updates the cache before returning the result.
**/
class UserMediator: UserApiService(), UserCacheService() {
}

Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΉ Π²Ρ‹ΡˆΠ΅ ΠΊΠΎΠ΄ Π½Π΅ компилируСтся. И Π΄Π°ΠΆΠ΅ Ссли Π±Ρ‹ это Π±Ρ‹Π»ΠΎ Ρ‚Π°ΠΊ, ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ Π½Π΅ ΠΈΠΌΠ΅Π»ΠΈ Π±Ρ‹ смысла, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ, вмСсто Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π±Ρ‹Ρ‚ΡŒ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡΠΌΠΈ, UserMediatorΒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ UserCacheService ΠΈ UserApiServiceΒ Π² качСствС Π΄Π΅Ρ‚Π°Π»Π΅ΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.Β Π’Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ это ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ, ΠΏΠΎΠ·ΠΆΠ΅.

ВСсная связь (Tight Coupling)

РСализация наслСдования создаСт ΠΏΡ€ΠΎΡ‡Π½ΡƒΡŽ связь ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»Π΅ΠΌ ΠΈ Π΅Π³ΠΎ подклассами. НаслСдованиС класса привязываСт Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ класс ΠΊ дСталям Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ класса.Β Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, Ссли Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ класс измСняСтся - Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ словами, Ссли ΠΎΠ½ нСстабилСн - Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ класс ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ, Π΄Π°ΠΆΠ΅ Ссли Π΅Π³ΠΎ ΠΊΠΎΠ΄ Π½Π΅ измСнился.Β Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ класс Π΄ΠΎΠ»ΠΆΠ΅Π½ Π΄ΠΎΡ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒΡΡ вмСстС со своим Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΌ классом.

Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΠΎΡ‚ вас трСбуСтся Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΠ±Ρ‰ΠΈΡ… ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ ΠΎ Π±ΡƒΠ΄ΡƒΡ‰ΠΈΡ… трСбованиях.Β Π’Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π·Π°Ρ€Π°Π½Π΅Π΅ ΠΏΠΎΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡŽ ΠΈ ΡΠ»Π΅Π΄ΠΈΡ‚ΡŒ Π·Π° Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ ΠΎΡΡ‚Π°Π²Π°Π»ΠΈΡΡŒ Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ с Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π½ΠΎΠ²ΠΎΠ³ΠΎ трСбования.Β Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π²Π°ΠΌ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, придСтся ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΒ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ BDUF (Big Design Up Front), Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ Ρ‡Ρ€Π΅Π·ΠΌΠ΅Ρ€Π½ΠΎΠΌΡƒ тСхничСскому ΡƒΡΠ»ΠΎΠΆΠ½Π΅Π½ΠΈΡŽ ΠΈ слоТной конструкции.

Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅ Π²Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ наслСдованиС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π½Π°Ρ€ΡƒΡˆΠ°Π΅Ρ‚ ΠΈΠ½ΠΊΠ°ΠΏΡΡƒΠ»ΡΡ†ΠΈΡŽ.

НСобоснованноС раскрытиС API супСркласса

НаслСдованиС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ умСстно Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚Π΅Ρ… случаях, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΠ΄ΠΊΠ»Π°ΡΡΒ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ являСтся ΠΏΠΎΠ΄Ρ‚ΠΈΠΏΠΎΠΌ супСркласса.Β Π”Ρ€ΡƒΠ³ΠΈΠΌΠΈ словами, класс BΒ Π΄ΠΎΠ»ΠΆΠ΅Π½ Ρ€Π°ΡΡˆΠΈΡ€ΡΡ‚ΡŒ класс AΒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚ΠΎΠΌ случаС, Ссли ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ сущСствуСт связь Β«is-aΒ».Β Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС, Π²Ρ‹ излишнС раскрываСтС Π΄Π΅Ρ‚Π°Π»ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ супСркласса ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ.Β Π­Ρ‚ΠΎ ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ возмоТности для ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ² вашСго класса Π½Π°Ρ€ΡƒΡˆΠ°Ρ‚ΡŒ Π΅Π³ΠΎ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠ΅ ΠΈΠ½Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Ρ‹ ΠΏΡƒΡ‚Π΅ΠΌ нСпосрСдствСнного измСнСния супСркласса.

ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Π½Π°Β ExposureDemo.kt, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ находится Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚Π°Β exposuredemo. ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ properties являСтся экзСмпляром PropertiesΒ ΠΈΠ·Β ΠΏΠ°ΠΊΠ΅Ρ‚Π°Β java.util. Он унаслСдован ΠΎΡ‚ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π° Hashtable. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π²Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ общСдоступным полям ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ Hashtable, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, put() ΠΈ get(), Ρ‡Π΅Ρ€Π΅Π· экзСмпляр Properties вмСстС с собствСнными.Β 

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ прСдставлСниС ΠΎΠ± API-интСрфСйсах, прСдоставляСмых с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Properties, ΠΏΠ΅Ρ€Π΅ΠΉΠ΄ΠΈΡ‚Π΅ ΠΊΒ Properties.javaΒ (располоТСнному Π²Β java.util) Π² своСй срСдС IDE ΠΈ Ρ‰Π΅Π»ΠΊΠ½ΠΈΡ‚Π΅Β Π²ΠΊΠ»Π°Π΄ΠΊΡƒ Structure. Π’Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅ структуру PropertiesΒ Π½Π° Π±ΠΎΠΊΠΎΠ²ΠΎΠΉ ΠΏΠ°Π½Π΅Π»ΠΈ.

Β 

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π·Π½Π°Ρ‡ΠΊΠΈ Π² Π²Π΅Ρ€Ρ…Π½Π΅ΠΉ части ΠΏΠ°Π½Π΅Π»ΠΈ, снимитС Ρ„Π»Π°ΠΆΠΎΠΊΒ Show non-publicΒ ΠΈ Π²Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅Β Show inherited. Π’Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ ΠΏΠΎΡ…ΠΎΠΆΠ΅Π΅ Π½Π° ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π²Ρ‹ΡˆΠ΅. Π‘Π²Π΅Ρ‚Π»ΠΎ-сСрыС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ - это унаслСдованныС общСдоступныС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· экзСмпляр Properties.

// [Properties] class extends from Hashtable. So, the methods from Hashtable can also be used.
val properties = Properties()

// Using [Hashtable]'s methods
properties.put("put1", "val1")
properties.put("put2", 100)

// Using [Properties]'s methods
properties.setProperty("setProperty1", "val1")
properties.setProperty("setProperty2", "100")

Но Π΅ΡΡ‚ΡŒ Π·Π°Π³Π²ΠΎΠ·Π΄ΠΊΠ°. Если Π²Ρ‹ посмотритС Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ для Properties, Ρ‚ΠΎ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎ Π½Π΅ рСкомСндуСтся ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Hashtable, Π΄Π°ΠΆΠ΅ Ссли ΠΎΠ½ΠΈ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°.

// Note: [Properties] 'getProperty()' returns null if the type is not a String;
// However, [Hashtable] 'get()' returns the correct value
properties.propertyNames().toList().forEach {
  println("Using Hashtable's get() $it: ${properties.get(it)}")
  println("Using Properties' getProperty() $it :  ${properties.getProperty(it.toString())}")
  println()
}

getProperty() ΠΈΠ·Β Property ΠΈΠΌΠ΅Π΅Ρ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ бСзопасности касаСмо Ρ‚ΠΎΠ³ΠΎ, выполняСтся Π»ΠΈ get()Β ΠΈΠ· этого Hashtable ΠΈΠ»ΠΈ Π½Π΅Ρ‚.Β ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ PropertiesΒ ΠΌΠΎΠ³ΡƒΡ‚ ΠΎΠ±ΠΎΠΉΡ‚ΠΈ эти ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΈ Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ прямо ΠΈΠ· Hashtable.Β Π’ΠΎΡ‚ ΠΏΠΎΡ‡Π΅ΠΌΡƒ, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ запускаСтС Ρ„Π°ΠΉΠ», Π²Ρ‹ Π²ΠΈΠ΄ΠΈΡ‚Π΅ Π²Ρ‹Π²ΠΎΠ΄, ΠΏΠΎΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ Π½ΠΈΠΆΠ΅, Π² консоли:

Using Hashtable's get() setProperty2: 100
Using Properties' getProperty() setProperty2 :  100

Using Hashtable's get() setProperty1: val1
Using Properties' getProperty() setProperty1 :  val1

Using Hashtable's get() put2: 100
Using Properties' getProperty() put2 :  null

Using Hashtable's get() put1: val1
Using Properties' getProperty() put1 :  val1

Для случаСв, ΠΊΠΎΠ³Π΄Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ относится ΠΊ Ρ‚ΠΈΠΏΡƒ String, getProperty() ΠΈ get(),Π² ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠΌ Π²Ρ‹ΡˆΠ΅ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Ρ‹ Ρ€Π°Π·Π½Ρ‹Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ для ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ ΠΊΠ»ΡŽΡ‡Π°.Β Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΡ‹ΠΉ API Π²Π²ΠΎΠ΄ΠΈΡ‚ Π² Π·Π°Π±Π»ΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Π²Π΅Ρ€ΠΆΠ΅Π½ ΠΎΡˆΠΈΠ±ΠΎΡ‡Π½Ρ‹ΠΌ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌ.

Π”Π°Π»Π΅Π΅ Π²Ρ‹ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅, ΠΊΠ°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²ΠΎΠ΅ наслСдованиС ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ ΡƒΠ²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΡŽ числа подклассов.

Π£Π²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΠ΅ числа подклассов

Kotlin Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ мноТСствСнноС наслСдованиС. Но ΠΎΠ½ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚Β ΠΌΠ½ΠΎΠ³ΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²ΠΎΠ΅ наслСдованиС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ довольно часто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ. НапримСр, Android SDK прСдоставляСт TextView, наслСдуСмый ΠΎΡ‚ View. Π’Π΅ΠΏΠ΅Ρ€ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ для TextViewΒ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ HTML, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ HtmlTextView, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠ²Π»ΡΡ‚ΡŒΡΡ наслСдником ΠΎΡ‚ TextView.Β Π’Π°ΠΊ выглядит ΠΌΠ½ΠΎΠ³ΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²ΠΎΠ΅ наслСдованиС.

Β 

ВспомнитС ΠΏΡ€ΠΈΠΌΠ΅Ρ€ с PizzaΒ ΠΈΠ· ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ Ρ€Π°Π·Π΄Π΅Π»Π°. Он ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ - Ρ‚ΠΈΠΏ ΠΏΠΈΡ†Ρ†Ρ‹ (вСгСтарианская ΠΈ сырная), Ρ‡Ρ‚ΠΎ Π±Ρ‹Π»ΠΎ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΠΏΡ€ΠΈ написании ΠΊΠΎΠ΄Π°. ПозТС ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Ρ…ΠΎΡ‡Π΅Ρ‚ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΏΠΈΡ†Ρ†Ρƒ Ρ€Π°Π·Π½Ρ‹Ρ… Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠ² - ΠΌΠ°Π»Π΅Π½ΡŒΠΊΡƒΡŽ, ΡΡ€Π΅Π΄Π½ΡŽΡŽ ΠΈ Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ.Β Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Ρƒ вас Π΅ΡΡ‚ΡŒ Π΄Π²Π° нСзависимых ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° - Ρ‚ΠΈΠΏ ΠΈ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΏΠΈΡ†Ρ†Ρ‹.

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π½Π΅Ρ‚ смысла ΠΎΡ‚Π΄Π΅Π»ΡΡ‚ΡŒ ΠΏΠΈΡ†Ρ†Ρƒ ΠΎΡ‚ Π΅Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Π°, Π²Ρ‹ Π΄Π΅Π»Π°Π΅Ρ‚Π΅ CheesePizzaΒ ΠΈ VeggiePizza абстрактными.Β Π—Π°Ρ‚Π΅ΠΌ Π²Ρ‹ Ρ€Π΅ΡˆΠ°Π΅Ρ‚Π΅ Ρ€Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ ΠΈΡ… для добавлСния Ρ€Π°Π·ΠΌΠ΅Ρ€Π°, создав ΠΏΠΎ Ρ‚Ρ€ΠΈ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹Ρ… Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° ΠΏΠΈΡ†Ρ†Ρ‹.Β Π˜Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΡ‡Π΅ΡΡ‚ΡŒ Π½ΠΎΠ²ΠΎΠ΅ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅, Π²Ρ‹ Ρ€Π΅ΠΎΡ€Π³Π°Π½ΠΈΠ·ΡƒΠ΅Ρ‚Π΅ ΠΊΠΎΠ΄, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½ΠΈΠΆΠ΅:

abstract class Pizza {
  abstract fun prepare()
}

abstract class CheesePizza : Pizza()
abstract class VeggiePizza : Pizza()

class SmallCheesePizza : CheesePizza() {
  override fun prepare() {
    println("Prepared a small cheese pizza")
  }
}

class MediumCheesePizza : CheesePizza() {
  override fun prepare() {
    println("Prepared a medium cheese pizza")
  }
}

class LargeCheesePizza : CheesePizza() {
  override fun prepare() {
    println("Prepared a large cheese pizza")
  }
}

class SmallVeggiePizza : VeggiePizza() {
  override fun prepare() {
    println("Prepared a small veggie pizza")
  }
}

class MediumVeggiePizza : VeggiePizza() {
  override fun prepare() {
    println("Prepared a medium veggie pizza")
  }
}

class LargeVeggiePizza : VeggiePizza() {
  override fun prepare() {
    println("Prepared a large veggie pizza")
  }
}

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹Ρ€Π°Π·ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ Π²Ρ‹ΡˆΠ΅ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ Π² Π²ΠΈΠ΄Π΅ Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΡ‹ классов ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

Β 

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ с этой Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ. ИмСя всСго Ρ‚Ρ€ΠΈ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° ΠΈ Π΄Π²Π° Ρ‚ΠΈΠΏΠ° ΠΏΠΈΡ†Ρ†Ρ‹, Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚Π΅ подклассы 3*2. Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° для любого ΠΈΠ· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ»ΠΎ Π±Ρ‹ количСство подклассов. Π‘ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΠ³ΠΎ, Ссли Π²Ρ‹ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚Π΅ сигнатуру CheesePizza, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ cheeseNameΒ Π² Π΅Π³ΠΎ конструктор, ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ распространится Π½Π° всС подклассы.

Π˜Ρ‚Π°ΠΊ, ΠΊΠ°ΠΊ Π²Ρ‹ ΡΠΏΡ€Π°Π²ΠΈΡ‚Π΅ΡΡŒ со всСми этими ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°ΠΌΠΈ?Β Π§Π΅Ρ€Π΅Π· использованиС ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ!

ΠšΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΡ

ΠšΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΡ - это ΠΌΠ΅Ρ‚ΠΎΠ΄, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ вы формируСтС класс ΠΏΡƒΡ‚Π΅ΠΌ добавлСния private ΠΏΠΎΠ»Π΅ΠΉ ΠΊ классу, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ссылаСтся Π½Π° экзСмпляр ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ класса, Π° Π½Π΅ Ρ€Π°ΡΡˆΠΈΡ€ΡΡŽΡ‚ Π΅Π³ΠΎ.Β Π’Π°ΠΊ Ρ‡Ρ‚ΠΎ связь Β«has-aΒ» устанавливаСтся ΠΌΠ΅ΠΆΠ΄Ρƒ composed классом ΠΈ содСрТащимися Π²Β Π½Π΅ΠΌ экзСмплярах. Класс выполняСт свои обязанности, пСрСнаправляя ΠΈΠ»ΠΈ вызывая non-private ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ своих private ΠΏΠΎΠ»Π΅ΠΉ.

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ UserMediator, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½ΠΈΠΆΠ΅:

class UserMediator {
  private val cacheService: UserCacheService = UserCacheService()
  private val apiService: UserApiService = UserApiService()

  // ...
}

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΠΊΠ°ΠΊ private экзСмпляры UserCacheServiceΒ ΠΈ UserApiServiceΒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ для создания UserMediator.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° Ρƒ вас Π΅ΡΡ‚ΡŒ Π±Π°Π·ΠΎΠ²ΠΎΠ΅ прСдставлСниС ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, ΠΏΠΎΡ€Π° ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ, ΠΊΠ°ΠΊ Π΅Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ проСктирования, Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‰ΠΈΡ… Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ наслСдования Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

Π Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³ с использованиСм ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ малСнькиС Π΄Π΅Ρ‚Π°Π»ΠΈ для создания слоТного ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.Β Π’ этом Ρ€Π°Π·Π΄Π΅Π»Π΅ Π²Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ этот ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π»ΠΈΠ±ΠΎ ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΡ‚ΡŒ число ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΏΡ€ΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ, Π²Ρ‹Π·Π²Π°Π½Π½Ρ‹Π΅ наслСдованиСм Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

Π Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³ класса UserMediator

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π²Ρ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ€Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ класса, самым простым устранСниСм нСисправности UserMediatorΒ Π±Ρ‹Π»ΠΎ Π±Ρ‹ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ³ΠΎ слова open ΠΈΠ· UserApiServiceΒ ΠΈ UserCacheService, Π½ΠΎ вмСсто этого сдСлайтС ΠΈΡ… частными полями экзСмпляра UserMediator, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π²ΠΎ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π΅ Π½ΠΈΠΆΠ΅:

class UserMediator {

  private val cacheService: UserCacheService = UserCacheService()
  private val apiService: UserApiService = UserApiService()

  /**
   * Search for [User] with [username] on cache first. If not found,
   * make API calls to fetch the [User] and persist it in server.
   *
   * @throws UserNotFoundException if it is not in the "server".
   */
  fun fetchUser(username: String): User {
    return cacheService.findUserById(username)
      ?: apiService.fetchUserByUsername(username)?.also { cacheService.saveUser(it) }
      ?: throw UserNotFoundException(username)
  }
}

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΠΊΠ°ΠΊ классы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ€Π°ΡΡˆΠΈΡ€ΡΡŽΡ‚ UserMediator,Β ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΡŽΡ‚ΡΡ Π² поля частных экзСмпляров этого ΠΆΠ΅ класса.

Π‘ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΠ³ΠΎ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ тСстированиС Π΄Π°Π½Π½ΠΎΠ³ΠΎ класса, приняв эти поля экзСмпляра Π² качСствС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² конструктора ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Π² созданиС этих ΠΏΠΎΠ»Π΅ΠΉ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ.Β Π­Ρ‚ΠΎ называСтся внСдрСниСм зависимостСй (dependency injection).

ΠžΡ‚ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ ΠΊ Π°Π³Ρ€Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ

Π£Π΄Π°Π»ΠΈΡ‚Π΅ эти Π΄Π²Π° поля ΠΈ создайтС конструктор для UserMediator, принимая эти Π΄Π²Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ экзСмпляра Π² качСствС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ²:

class UserMediator(
  private val cacheService: UserCacheService,
  private val apiService: UserApiService
) {
   // methods...
}

Π’ main()Β Π²Β UserDemo.kt скопируйтС ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄ для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ mediator:

val mediator = UserMediator(
  cacheService = UserCacheServiceImpl(),
  apiService = UserApiServiceImpl()
)

UserMediator Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ зависит ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ класса ΡƒΠΊΠ°ΠΆΠ΅Ρ‚ Π΅Π³ΠΎ зависимости. А Π²ΠΎ врСмя тСстирования Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ тСстовыС Π·Π°Π³Π»ΡƒΡˆΠΊΠΈ, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ нСпосрСдствСнно вашСй тСстовой ситуации, Ρ‡Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚ тСстированиС.

Π—Π°ΠΌΠ΅Ρ‚ΠΊΠ°

ΠšΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΡ - это сильная Ρ„ΠΎΡ€ΠΌΠ° ассоциации, Π±ΠΎΠ»Π΅Π΅ слабая Ρ„ΠΎΡ€ΠΌΠ° ассоциации называСтся Π°Π³Ρ€Π΅Π³Π°Ρ†ΠΈΠ΅ΠΉ. ΠŸΠ΅Ρ€Π²Π°Ρ пСрСсмотрСнная вСрсия UserMediatorΒ (с конструктором ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ) дСмонстрируСт ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΎΠ½Π½Ρ‹Π΅ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ с содСрТащимися Π² Π½Π΅ΠΉ экзСмплярами, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΈΡ… ΠΆΠΈΠ·Π½Π΅Π½Π½Ρ‹ΠΉ Ρ†ΠΈΠΊΠ» привязан ΠΊ ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠΌΡƒ Ρ†ΠΈΠΊΠ»Ρƒ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°. Напротив, вторая вСрсия UserMediatorΒ (с Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌΠΈ конструктора) дСмонстрируСт связь агрСгирования, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½Π° ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ прСдоставит зависимости. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, содСрТащиСся Π² Π½Π΅ΠΌ экзСмпляры ΠΌΠΎΠ³ΡƒΡ‚ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π΄Π°ΠΆΠ΅ послС уничтоТСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° UserMediator.

ΠŸΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚Π΅ курсор Π½Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ класса UserMediatorΒ ΠΈ Π½Π°ΠΆΠΌΠΈΡ‚Π΅Β Control-Enter.Β Π—Π°Ρ‚Π΅ΠΌ Π²Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅Β Create test. Боздастся Ρ„Π°ΠΉΠ» -Β UserMediatorTest.ktΒ - внутри тСстового каталога.Β ΠžΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ Π΅Π³ΠΎ ΠΈ Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚:

internal class UserMediatorTest {
  private lateinit var mockApi: UserApiService
  private lateinit var realCache: UserCacheService

  @BeforeEach
  fun setup() {
    // 1
    realCache = UserCacheServiceImpl()

    // 2
    mockApi = object : UserApiService {
      private val db = mutableListOf()

      init {
        db.add(User("testuser1", "Test User"))
      }

      override fun fetchUserByUsername(username: String): User? {
        return db.find { username == it.username }
      }
    }
  }

  @Test
  fun `Given username when fetchUser then should return user from cache and save it in cache`() {
    // 3
    val mediator = UserMediator(realCache, mockApi)
    val inputUsername = "testuser1"
    val user = mediator.fetchUser(inputUsername)
    assertNotNull(user)
    assertTrue { user.username == inputUsername }
    // Check if saved in cache
    assertNotNull(realCache.findUserById(inputUsername))
  }
}

Π’ΠΎΡ‚ пошаговоС объяснСниС Π»ΠΎΠ³ΠΈΠΊΠΈ прСдставлСнного Π²Ρ‹ΡˆΠ΅ ΠΊΠΎΠ΄Π°:

  1. Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ realCacheΒ ΠΊΠ°ΠΊ экзСмпляр UserCacheServiceImpl.Β ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ этот класс ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ структуру Π΄Π°Π½Π½Ρ‹Ρ… Π² памяти, Π²Π°ΠΌ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΈΠΌΠΈΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π³ΠΎ.
  2. ΠŸΡ€ΠΈ этом UserApiServiceImpl выполняСт «сСтСвой» Π²Ρ‹Π·ΠΎΠ², ΠΈ Π²Ρ‹ Π½Π΅ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ тСстовых случаСв зависСл ΠΎΡ‚ ΠΎΡ‚Π²Π΅Ρ‚Π° сСрвСра ΠΈΠ»ΠΈ Π΅Π³ΠΎ доступности.Β Π’Π°ΠΊ Ρ‡Ρ‚ΠΎ Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠΌΠΈΡ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΡƒΡŽ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΈΠ»ΠΈ Ρ‚Π΅ΡΡ‚ΠΎΠ²ΡƒΡŽ Π·Π°Π³Π»ΡƒΡˆΠΊΡƒ.Β Π’ Π΄Π°Π½Π½ΠΎΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π²Ρ‹ Π·Π°ΠΌΠ΅Π½ΠΈΠ»ΠΈ Π΅Π³ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ, которая ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ структуру Π΄Π°Π½Π½Ρ‹Ρ… Π² памяти, поэтому вы опрСдСляСтС Π΅Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π² соотвСтствии со своим тСстовым сцСнариСм.
  3. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ UserMediatorΒ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ экзСмпляры UserCacheServiceΒ ΠΈ Π² качСствС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² UserApiService, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Π΅ Π²Ρ‹ΡˆΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅.

Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅ Π²Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Π΄Π΅Ρ‚Π΅ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³ Ρ€Π°Π·Π±ΠΈΡ‚Ρ‹Ρ… Π½Π° части подклассов, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ.

Π Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³ класса ΠΏΠΈΡ†Ρ†Ρ‹

Π Π°Π½Π΅Π΅ Π²Ρ‹ Π²ΠΈΠ΄Π΅Π»ΠΈ, ΠΊΠ°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²ΠΎΠ΅ наслСдованиС ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Ρ€Π΅Π·ΠΊΠΎΠΌΡƒ ΡƒΠ²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΡŽ числа подклассов. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, Π½Π΅ модСлируя ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ Π² Ρ„ΠΎΡ€ΠΌΠ΅ ΠΌΠ½ΠΎΠ³ΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²ΠΎΠ³ΠΎ наслСдования, Π° вмСсто этого устанавливая связь Β«has-aΒ» ΠΌΠ΅ΠΆΠ΄Ρƒ PizzaΒ ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ.

ΠžΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅Β Ρ„Π°ΠΉΠ» Pizza.kt Π²Π½ΡƒΡ‚Ρ€ΠΈΒ ΠΏΠ°ΠΊΠ΅Ρ‚Π° explosionofsubclassesdemo ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ содСрТимоС ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ΠΎΠΌ:

import java.math.RoundingMode

// 1
sealed class PizzaType {
  data class Cheese(val cheeseName: String) : PizzaType()
  data class Veggie(val vegetables: List) : PizzaType()
}

enum class Size(val value: Int) {
  LARGE(12), MED(8), SMALL(6);

  fun calculateArea(): Double {
    // Area of circle given diameter
    return (Math.PI / 4).toBigDecimal().setScale(2, RoundingMode.UP).toDouble() * value * value
  }
}

// 2
class Pizza(val type: PizzaType, val size: Size) {
  fun prepare() {
    // 3 
    println("Prepared ${size.name} sized $type pizza of area ${size.calculateArea()}")
  }
}

Π’ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠΌ Π²Ρ‹ΡˆΠ΅ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π΅ ΠΊΠΎΠ΄Π° происходит:

  1. Π’Ρ‹Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ классы PizzaType ΠΈ Size.
  2. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ класс ссылаСтся Π½Π° экзСмпляр ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½Π½ΠΎΠ³ΠΎ класса. Π—Π΄Π΅ΡΡŒ класс Pizza состоит ΠΈΠ· Π΄Π²ΡƒΡ…ΠΌΠ΅Ρ€Π½Ρ‹Ρ… классов.
  3. Π‘Π΄Π΅Π»Π°ΠΉΡ‚Π΅ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ composed класс Π΄Π΅Π»Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π» Π»ΡŽΠ±Ρ‹Π΅ вычислСния, связанныС с Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ, классу Size ΠΈ Π»ΡŽΠ±Ρ‹Π΅ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ вычислСния, относящиСся ΠΊ классу PizzaType.Β Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ composed класс выполняСт свою Ρ€ΠΎΠ»ΡŒ: взаимодСйствуСт с полями экзСмпляра.

НаконСц, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ класс, ΠΎΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅Β PizzaDemo.kt ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΊΠΎΠ΄ Π² main()Β Π½Π°:

val largeCheesePizza = Pizza(Cheese("Mozzarella"), Size.LARGE)
val smallVeggiePizza = Pizza(Veggie(listOf("Spinach", "Onion")), Size.SMALL)
val orders = listOf(largeCheesePizza, smallVeggiePizza)

orders.forEach {
  it.prepare()
}

НаконСц, запуститС Ρ„Π°ΠΉΠ», ΠΈ Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚:

Prepared LARGE sized Cheese(cheeseName=Mozzarella) pizza of area 113.76
Prepared SMALL sized Veggie(vegetables=[Spinach, Onion]) pizza of area 28.44

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ этой Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ ΠΊ Π»ΡŽΠ±ΠΎΠΌΡƒ ΠΈΠ· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ², Π½Π΅ бСспокоясь ΠΎ быстром ростС числа подклассов.

Π”Π°Π»Π΅Π΅ Π²Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, для управлСния ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ΠΌ API.

РСшСниС ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ экспозиции

ЭмпиричСскоС ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ Π² ООП гласит – слСдуСт ΠΏΠΈΡΠ°Ρ‚ΡŒΒ shy class (Β«ΡΡ‚Π΅ΡΠ½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ класс»).Β Shy class класс нС раскрываСт Π΄Ρ€ΡƒΠ³ΠΈΠΌ Π½Π΅Π½ΡƒΠΆΠ½ΡƒΡŽ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΎ сСбС. PropertiesΒ Java.util явно Π½Π°Ρ€ΡƒΡˆΠ°ΡŽΡ‚ это.Β Π›ΡƒΡ‡ΡˆΠΈΠΌ способом Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ стал Π±Ρ‹ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ.

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Properties - это встроСнный класс, прСдоставляСмый JDK, Π²Ρ‹ Π½Π΅ смоТСтС Π΅Π³ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ.Β Π˜Ρ‚Π°ΠΊ, Π²Ρ‹ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅, ΠΊΠ°ΠΊ это ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠΈΡ‚ΡŒ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΡƒΠΏΡ€ΠΎΡ‰Π΅Π½Π½ΠΎΠΉ вСрсии. Для этого создайтС Π½ΠΎΠ²Ρ‹ΠΉ класс HashtableStoreΒ ΠΈ Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚:

class HashtableStore {
  // 1
  private val store: Hashtable = Hashtable()

  // 2
  fun getProperty(key: String): String? {
    return store[key]
  }

  fun setProperty(key: String, value: String) {
    store[key] = value
  }

  fun propertyNames() = store.keys
}

Π’ΠΎΡ‚ пошаговоС объяснСниС Π»ΠΎΠ³ΠΈΠΊΠΈ ΠΊΠΎΠ΄Π°:

  1. ΠŸΡ€ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π΅, основанном Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, Π²Ρ‹ создаСтС частноС ΠΏΠΎΠ»Π΅ HashtableStoreΒ ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚Π΅ Π΅Π³ΠΎ ΠΊΠ°ΠΊ экзСмпляр Hashtable.Β Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ хранСния Π΄Π°Π½Π½Ρ‹Ρ…, Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ с этим экзСмпляром. ВспомнитС эмпиричСскоС ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ: ΠΏΠΈΡˆΠΈΡ‚Π΅ shy class. Если ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ экзСмпляр Π·Π°ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ, посторонниС Π½Π΅ смогут ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΊ Π½Π΅ΠΌΡƒ доступ, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π²Π°ΠΌ Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ инкапсуляции!
  2. Π’Ρ‹ прСдоставляСтС общСдоступныС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π΄Π°Π½Π½ΠΎΠ³ΠΎ класса.Β Π­Ρ‚ΠΎΡ‚ класс прСдоставляСт Ρ‚Ρ€ΠΈ Ρ‚Π°ΠΊΠΈΡ… ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, ΠΈ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ пСрСнаправляСт свою ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² privateΒ ΠΏΠΎΠ»Π΅.

Π’ Ρ‚ΠΎΠΌ ΠΆΠ΅ Ρ„Π°ΠΉΠ»Π΅ создайтС main() ΠΈ Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ Π² Π½Π΅Π³ΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄:

val properties = HashtableStore()

properties.setProperty("setProperty1", "val1")
properties.setProperty("setProperty2", "100")

properties.propertyNames().toList().forEach {
  println("$it: ${properties.getProperty(it.toString())}")
}

Если Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ всС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ PropertiesΒ Π²Ρ‹Π·Ρ‹Π²Π°Π»ΠΈΡΡŒ, сохраняя Β«ΠΎΠ±Π»Π°ΡΡ‚ΡŒ воздСйствия» ΠΏΠΎΠ΄ вашим ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π΅ΠΌ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΠ±ΠΎΠ»ΠΎΡ‡ΠΊΡƒ Π²ΠΎΠΊΡ€ΡƒΠ³ Π½Π΅Π΅ ΠΈ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ свои собствСнныС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Π½ΠΎΠ²Ρ‹ΠΉ класс PropertiesStoreΒ ΠΈ Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄:

class PropertiesStore {
  private val properties = Properties()

  fun getProperty(key: String): String? {
    return properties.getProperty(key)
  }

  fun setProperty(key: String, value: String) {
    properties.setProperty(key, value)
  }

  fun propertyNames() = properties.propertyNames()
}

Как элСмСнт HashtableStore, PropertiesStoreΒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ private экзСмпляр, Π½ΠΎ ΠΏΡ€ΠΈ этом public ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‚ с Properties. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ PropertiesΒ Π² качСствС поля экзСмпляра, Π²Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ прСимущСства ΠΎΡ‚ Π»ΡŽΠ±Ρ‹Ρ… Π±ΡƒΠ΄ΡƒΡ‰ΠΈΡ… ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ Properties.Β 

Π’Ρ‹ ΡƒΠ·Π½Π°Π»ΠΈ, ΠΊΠ°ΠΊ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠΌΠΎΡ‡ΡŒ Π²Π°ΠΌ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ Π΄ΠΈΠ·Π°ΠΉΠ½Π°.Β Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅ Π²Ρ‹ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅ ΠΎ Π΅Π³ΠΎ нСдостатках.

ИспользованиС наслСдования

К настоящСму ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρƒ Π²Ρ‹, Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ, спроситС: Β«ΠŸΠΎΡ‡Π΅ΠΌΡƒ Π±Ρ‹ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ?Β». Π’Π΅Π΄ΡŒ ΠΊΠ°ΠΊ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ всСгда ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ. Π›ΡŽΠ±ΠΎΠΉ класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ Ρ‡Π΅Ρ€Π΅Π· наслСдованиС, Π² качСствС Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ с использованиСм ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ. Но Π΅ΡΡ‚ΡŒ случаи, ΠΊΠΎΠ³Π΄Π° использованиС наслСдования оказываСтся Π±ΠΎΠ»Π΅Π΅ Π²Ρ‹Π³ΠΎΠ΄Π½Ρ‹ΠΌ.

НаслСдованиС - мощная концСпция. И Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… мСстах. НапримСр, Π² Android SDK TextViewΒ Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ View. Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½Π°ΡΡ‚Ρ€ΠΎΠ΅Π½Π½ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ TextView, Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ TextViewΒ ΠΈ прСдоставляСт Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΈΠ»ΠΈ измСняСт ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ Ρ„ΠΎΡ€ΠΌΡ‹ повСдСния. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π° класса Π΄Π΅ΠΌΠΎΠ½ΡΡ‚Ρ€ΠΈΡ€ΡƒΡŽΡ‚ Β«is-aΒ» ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ с View, ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ Π²Π΅Π·Π΄Π΅, Π³Π΄Π΅ ViewΒ ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌ (ΠΏΠΎΠΌΠ½ΠΈΡ‚Π΅ ΠΎ взаимозамСняСмости?). Вакая Π·Π°ΠΌΠ΅Π½Π° Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ простого ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π°, основанного Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, PropertiesStoreΒ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΌΠ΅Π½Π΅Π½ΠΎ Π½Π° Hashtable, ΠΊΠ°ΠΊ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Properties.

Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ наслСдования Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, композиция Π½Π΅ обСспСчиваСт автоматичСского дСлСгирования. ВмСсто этого Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ явно ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ с Π΅Π³ΠΎ полями экзСмпляра, вызывая ΠΈΡ… ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹. Если Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„Π½ΠΎΠ³ΠΎ повСдСния ΠΎΡ‚ composed класса, Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π³ΠΎ с интСрфСйсами ΠΈ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ большоС количСство Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² дСлСгирования ΠΈΠ»ΠΈ пСрСадрСсации.

Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, прСдоставляСмыС ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ, ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹ Π² composed классС, Π΄Π°ΠΆΠ΅ Ссли ΠΎΠ½ΠΈ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌΠΈ пСрСадрСсации. Напротив, ΠΏΡ€ΠΈ наслСдовании Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… отличаСтся ΠΎΡ‚ повСдСния ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса.

Π’Ρ‹Π±ΠΎΡ€ ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° зависит ΠΎΡ‚ Ρ…Π°Ρ€Π°ΠΊΡ‚Π΅Ρ€Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π²Ρ‹ ΠΏΡ‹Ρ‚Π°Π΅Ρ‚Π΅ΡΡŒ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ. НаслСдованиС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ…ΠΎΡ€ΠΎΡˆΠΎ Π²ΠΎ всСх случаях, Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ Ρ‚Π΅Ρ…, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ Π΅Π³ΠΎ ΠΊΠ°ΠΊ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π½Π΅ для Ρ‚ΠΎΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹.Β Π’ΠΎΠ³Π΄Π° это ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΌ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°ΠΌ - ΠΈΠ½ΠΎΠ³Π΄Π° Π΄ΠΎ Ρ‚Π°ΠΊΠΎΠΉ стСпСни, Ρ‡Ρ‚ΠΎ классы становятся тСсно связанными, Π° обслуТиваниС - Π·Π°Ρ‚Ρ€ΡƒΠ΄Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ.

Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅ Π²Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ написания шаблона дСлСгирования с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Kotlin.

Π¨Π°Π±Π»ΠΎΠ½ дСлСгирования Π² Kotlin

Как Π²Ρ‹ ΡƒΠ·Π½Π°Π»ΠΈ Ρ€Π°Π½Π΅Π΅, композиция с использованиСм интСрфСйсов ΠΈ пСрСадрСсации Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„Π½ΠΎΠ³ΠΎ повСдСния composed классов. Но для этого Π½ΡƒΠΆΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ пСрСсылки.Β Kotlin прСдоставляСт Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π΄Π°Π½Π½ΠΎΠ³ΠΎ шаблона дСлСгирования. Но сначала Π²Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ это дСлаСтся самым простым способом.

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅Β Ρ„Π°ΠΉΠ»Β DelegationDemo.ktΒ ΠΈ Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ этот Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚:

data class Result(val item: T)

// 1
interface CanCook {
  fun cook(item: T): Result
}

// 2
class PizzaCookingTrait : CanCook {

  override fun cook(item: Pizza): Result {
    println("Collecting ingredients")
    item.prepare()
    return Result(item)
  }
}

// 3
class Chef(private val trait: CanCook) : CanCook {
  override fun cook(item: T): Result {
    return trait.cook(item)
  }
}

fun main() {
  val pizza = Pizza(PizzaType.Cheese("Mozzarella"), Size.LARGE)
  val chef = Chef(trait = PizzaCookingTrait())
  chef.cook(pizza)
}

Β Π’ΠΎΡ‚ пошаговоС Ρ€Π°Π·ΡŠΡΡΠ½Π΅Π½ΠΈΠ΅ Π»ΠΎΠ³ΠΈΠΊΠΈ ΠΊΠΎΠ΄Π°:

  1. CanCook- это интСрфСйс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ Π»ΡŽΠ±Ρ‹ΠΌ классом, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΠΌΠ΅Π΅Ρ‚ элСмСнт cook() Ρ‚ΠΈΠΏΠ° T.
  2. cook() ΠΈΠ· PizzaCookingTrait ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ PizzaΒ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π³ΠΎΡ‚ΠΎΠ²ΠΎΠ΅ блюдо Result.
  3. Chef состоит ΠΈΠ· поля экзСмпляра trait ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ CanCook. ΠŸΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π΄Π΅Π»Π΅Π³ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ своСму полю экзСмпляра cook().

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ написания Ρ‚Π°ΠΊΠΈΡ… Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² пСрСадрСсации, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ by, ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово Kotlin,Β Π·Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ слСдуСт экзСмпляр, Π½ΡƒΠΆΠ΄Π°ΡŽΡ‰ΠΈΠΉΡΡ Π² Π΄Π΅Π»Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½ΠΈΠΆΠ΅:

class Chef(private val trait: CanCook) : CanCook by trait

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π² мСню Π²Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅ View > Show BytecodeΒ ΠΈ Π½Π°ΠΆΠΌΠΈΡ‚Π΅ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ Decompile. Π’Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ эквивалСнтный ΠΊΠΎΠ΄ Java. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠ΅Ρ€Π΅ΠΉΠ΄ΠΈΡ‚Π΅ ΠΊ Chef этого Java-Ρ„Π°ΠΉΠ»Π°, ΠΈ Π²Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π²Ρ€ΠΎΠ΄Π΅ этого:

import kotlin.jvm.internal.Intrinsics;

// ...

public final class Chef implements CanCook {
  private final CanCook trait;

  public Chef(@NotNull CanCook trait) {
    Intrinsics.checkNotNullParameter(trait, "trait");
    super();
    this.trait = trait;
  }

  @NotNull
  public Result cook(Object item) {
    return this.trait.cook(item);
  }
}  

Π£Π΄Π΅Π»ΠΈΡ‚Π΅ нСсколько ΠΌΠΈΠ½ΡƒΡ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΡ€Π°Π²Π½ΠΈΡ‚ΡŒ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΉ Π²Ρ‹ΡˆΠ΅ ΠΊΠΎΠ΄ с классичСской Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Chef. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΈ ΠΏΠΎΡ…ΠΎΠΆΠΈ. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, byΒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π² классичСской вСрсии Π΄Π΅Π»Π΅Π³Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ΄Π°.

Π’Ρ‹ ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ ΠΏΠΎΡ‚Ρ€ΡƒΠ΄ΠΈΠ»ΠΈΡΡŒ Π²ΠΎ врСмя изучСния ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² ΡƒΡ€ΠΎΠΊΠ°!Β Π’Ρ‹ ΡƒΠ·Π½Π°Π»ΠΈ ΠΎ Π΄Π²ΡƒΡ… Ρ€Π°Π·Π½Ρ‹Ρ… способах установлСния ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠΉ ΠΌΠ΅ΠΆΠ΄Ρƒ классами.Β ΠŸΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, позволяСт ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ нСбольшой Π°Π²Ρ‚ΠΎΠ½ΠΎΠΌΠ½Ρ‹ΠΉ класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ классами для создания высокоинкапсулированного, Π»Π΅Π³ΠΊΠΎ тСстируСмого ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½ΠΎΠ³ΠΎ класса.Β ΠŸΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° наслСдовании, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ прСимущСство ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ Β«is-aΒ» ΠΌΠ΅ΠΆΠ΄Ρƒ классами для обСспСчСния высокой стСпСни ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠ³ΠΎ использования ΠΊΠΎΠ΄Π° ΠΈ ΠΌΠΎΡ‰Π½ΠΎΠ³ΠΎ дСлСгирования. Однако ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, основанный Π½Π° наслСдовании, слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚ΠΎΠΌ случаС, Ссли ΠΏΠΎΠ΄Ρ‚ΠΈΠΏΡ‹ ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€ΡΡŽΡ‚ ΡƒΡΠ»ΠΎΠ²ΠΈΡŽ Β«is-aΒ».

ΠžΡ€ΠΈΠ³ΠΈΠ½Π°Π» ΡΡ‚Π°Ρ‚ΡŒΠΈ


ΠžΡ†Π΅Π½ΠΈΡ‚Π΅ ΡΡ‚Π°Ρ‚ΡŒΡŽ
0
0
0
0
0

Π§Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ, Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·ΡƒΠΉΡ‚Π΅ΡΡŒ
Π’ΠΎΠΉΡ‚ΠΈ
Акулов Иван Борисович
ΠŸΠΈΡˆΠ΅Ρ‚ ΠΈ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΈΡ‚ ΡΡ‚Π°Ρ‚ΡŒΠΈ для SwiftBook