From 1c7b6ae5df5e9f373745c24ddb3dcca4c1a8c383 Mon Sep 17 00:00:00 2001 From: YURY TILMAN Date: Mon, 25 Aug 2025 22:28:18 +0300 Subject: [PATCH 1/7] Change kotlin version to supported --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index dcb6872..df07d71 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.jetbrains.kotlin.jvm' version '2.2.10' + id 'org.jetbrains.kotlin.jvm' version '2.0.21' } kotlin { From f93970ab29061db655f119b314a1bd19dc7ececb Mon Sep 17 00:00:00 2001 From: YURY TILMAN Date: Mon, 25 Aug 2025 22:32:00 +0300 Subject: [PATCH 2/7] Implement task#1 --- src/main/kotlin/ru/otus/homework/homework/processList.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/ru/otus/homework/homework/processList.kt b/src/main/kotlin/ru/otus/homework/homework/processList.kt index 6d8ab43..fa9940e 100644 --- a/src/main/kotlin/ru/otus/homework/homework/processList.kt +++ b/src/main/kotlin/ru/otus/homework/homework/processList.kt @@ -8,7 +8,7 @@ inline fun processList(list: List, action: (Int) -> Unit) { fun skipThreeAndPrint(list: List) { processList(list) { - if (it == 3) return + if (it == 3) return@processList println("Processing $it") } } From f6f69928b1f686636edb3687bbf0775ba4054a42 Mon Sep 17 00:00:00 2001 From: YURY TILMAN Date: Mon, 25 Aug 2025 22:42:59 +0300 Subject: [PATCH 3/7] Implement task#2 mandatory --- .../ru/otus/homework/homework/Coffee.kt | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/ru/otus/homework/homework/Coffee.kt b/src/main/kotlin/ru/otus/homework/homework/Coffee.kt index c73f420..6b7232a 100644 --- a/src/main/kotlin/ru/otus/homework/homework/Coffee.kt +++ b/src/main/kotlin/ru/otus/homework/homework/Coffee.kt @@ -21,31 +21,16 @@ class SimpleCoffee : Coffee { } class MilkDecorator(private val coffee: Coffee) : Coffee { - override fun cost(): Int { - TODO("Not yet implemented") - } - - override fun description(): String { - TODO("Not yet implemented") - } + override fun cost() = coffee.cost() + 50 + override fun description(): String = coffee.description() + ", молоко" } class SugarDecorator(private val coffee: Coffee) : Coffee { - override fun cost(): Int { - TODO("Not yet implemented") - } - - override fun description(): String { - TODO("Not yet implemented") - } + override fun cost() = coffee.cost() + 20 + override fun description() = coffee.description() + ", сахар" } class VanillaDecorator(private val coffee: Coffee) : Coffee { - override fun cost(): Int { - TODO("Not yet implemented") - } - - override fun description(): String { - TODO("Not yet implemented") - } + override fun cost() = coffee.cost() + 70 + override fun description(): String = coffee.description() + ", ваниль" } \ No newline at end of file From 2b5fd77897d9894e3a7d9a0442f33b76411d88d1 Mon Sep 17 00:00:00 2001 From: YURY TILMAN Date: Mon, 25 Aug 2025 22:57:55 +0300 Subject: [PATCH 4/7] Implement task#2 optional --- .../ru/otus/homework/homework/Coffee.kt | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/ru/otus/homework/homework/Coffee.kt b/src/main/kotlin/ru/otus/homework/homework/Coffee.kt index 6b7232a..f199a1b 100644 --- a/src/main/kotlin/ru/otus/homework/homework/Coffee.kt +++ b/src/main/kotlin/ru/otus/homework/homework/Coffee.kt @@ -20,17 +20,26 @@ class SimpleCoffee : Coffee { override fun description() = "Простой кофе" } -class MilkDecorator(private val coffee: Coffee) : Coffee { - override fun cost() = coffee.cost() + 50 - override fun description(): String = coffee.description() + ", молоко" +// Абстрактный базовый класс для декораций +abstract class AbstractDecorator(protected val decoratedCoffee: Coffee) : Coffee { + protected abstract val additionalCost: Int + protected abstract val additionalDescription: String + + final override fun cost() = decoratedCoffee.cost() + additionalCost + final override fun description() = "${decoratedCoffee.description()}, $additionalDescription" +} + +class MilkDecorator(coffee: Coffee) : AbstractDecorator(coffee) { + override val additionalCost = 50 + override val additionalDescription = "молоко" } -class SugarDecorator(private val coffee: Coffee) : Coffee { - override fun cost() = coffee.cost() + 20 - override fun description() = coffee.description() + ", сахар" +class SugarDecorator(decoratedCoffee: Coffee) : AbstractDecorator(decoratedCoffee) { + override val additionalCost = 20 + override val additionalDescription = "сахар" } -class VanillaDecorator(private val coffee: Coffee) : Coffee { - override fun cost() = coffee.cost() + 70 - override fun description(): String = coffee.description() + ", ваниль" +class VanillaDecorator(decoratedCoffee: Coffee) : AbstractDecorator(decoratedCoffee) { + override val additionalCost = 70 + override val additionalDescription = "ваниль" } \ No newline at end of file From 8a5a8bfddb4c1f0137394cd5cbe050fcc487ee3f Mon Sep 17 00:00:00 2001 From: YURY TILMAN Date: Mon, 25 Aug 2025 23:24:40 +0300 Subject: [PATCH 5/7] Implement task#3.1 optional --- .../ru/otus/homework/homework/UserProfile.kt | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt b/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt index f0fab82..e913952 100644 --- a/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt +++ b/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt @@ -2,6 +2,8 @@ package ru.otus.homework.homework +import kotlin.reflect.KProperty + /** * Профиль пользователя */ @@ -50,4 +52,26 @@ private val emailRegex = Regex("^[A-Za-z](.*)([@])(.+)(\\.)(.+)") /** * Реализация простого [UserProfile]. */ -private class ProfileImplementation(override var fullName: String, override var email: String): UserProfile \ No newline at end of file +private class ProfileImplementation( + override var fullName: String, + email: String +) : UserProfile { + val vetoable = VetoableEmail(email) + override var email: String by vetoable +} + +class VetoableEmail( + var email: String +) { + + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + if (value.matches(emailRegex)) + email = value + else + System.err.println("veto placed on invalid email $value") + } + + operator fun getValue(hisRef: Any?, property: KProperty<*>): String { + return this.email + } +} \ No newline at end of file From c51e8236e15b71321338626a513021f4bf6f3915 Mon Sep 17 00:00:00 2001 From: YURY TILMAN Date: Mon, 25 Aug 2025 23:44:56 +0300 Subject: [PATCH 6/7] task#3.1 fix. Implement task#3.2 --- .../homework/NonEmptyStringDelegate.kt | 11 +++++++++-- .../ru/otus/homework/homework/UserProfile.kt | 18 ++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/ru/otus/homework/homework/NonEmptyStringDelegate.kt b/src/main/kotlin/ru/otus/homework/homework/NonEmptyStringDelegate.kt index 568f368..4161a0b 100644 --- a/src/main/kotlin/ru/otus/homework/homework/NonEmptyStringDelegate.kt +++ b/src/main/kotlin/ru/otus/homework/homework/NonEmptyStringDelegate.kt @@ -1,16 +1,23 @@ package ru.otus.homework.homework + import kotlin.reflect.KProperty /** * Delegate that allows to set non-empty string value */ class NonEmptyStringDelegate() { + private var value: String = "" + operator fun getValue(thisRef: Any?, property: KProperty<*>): String { - TODO("Implement `getValue` function") + return value } operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: String) { - TODO("Implement `setValue` function") + if (newValue.isNotBlank()) { + this.value = newValue + } else { + System.err.println("Property ${property.name} cannot be empty") + } } } \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt b/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt index e913952..d32710d 100644 --- a/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt +++ b/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt @@ -53,17 +53,23 @@ private val emailRegex = Regex("^[A-Za-z](.*)([@])(.+)(\\.)(.+)") * Реализация простого [UserProfile]. */ private class ProfileImplementation( - override var fullName: String, + fullName: String, email: String ) : UserProfile { - val vetoable = VetoableEmail(email) + val vetoable = VetoableEmail() + val nonEmptyStringDelegate = NonEmptyStringDelegate() + override var fullName: String by nonEmptyStringDelegate override var email: String by vetoable -} -class VetoableEmail( - var email: String -) { + init { + this.fullName = fullName + this.email = email + } + +} +class VetoableEmail { + var email: String = "" operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { if (value.matches(emailRegex)) email = value From fefc3f0b8823b6c87888979d4910b6f4c55eefbe Mon Sep 17 00:00:00 2001 From: YURY TILMAN Date: Tue, 26 Aug 2025 00:08:31 +0300 Subject: [PATCH 7/7] Implement task#3.3 --- .../ru/otus/homework/homework/UserProfile.kt | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt b/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt index d32710d..660d116 100644 --- a/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt +++ b/src/main/kotlin/ru/otus/homework/homework/UserProfile.kt @@ -39,7 +39,9 @@ interface UserProfile { * Creates user profile with logging */ fun createWithLogging(fullName: String, email: String): UserProfile.Logging { - TODO("Implement `createWithLogging` function") + return ProfileImplementationWithLogging( + create(fullName, email) + ) } } } @@ -68,6 +70,31 @@ private class ProfileImplementation( } +/** + * Реализация [UserProfile.Logging]. + */ +private class ProfileImplementationWithLogging( + val userProfile: UserProfile +) : UserProfile.Logging, UserProfile by userProfile { + private val log = mutableListOf() + + override var fullName: String + get() = userProfile.fullName + set(value) { + log.add("Changing `fullName` from '${userProfile.fullName}' to '$value'") + userProfile.fullName = value + } + + override var email: String + get() = userProfile.email + set(value) { + log.add("Changing `email` from '${userProfile.email}' to '$value'") + userProfile.email = value + } + + override fun getLog(): List = log +} + class VetoableEmail { var email: String = "" operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {