1
1
Fork 0

Modified ex 2 in class delegation

This commit is contained in:
Svetlana Isakova 2020-07-31 14:05:37 +02:00
parent 6e498e2ab6
commit c6598943c9
3 changed files with 58 additions and 45 deletions

View File

@ -1,44 +1,55 @@
// ClassDelegation/ClassDelegEx2.kt
package classDelegationExercise2
import usefullibrary.*
import atomictest.*
interface MyType {
fun g()
fun h()
import atomictest.trace
// Duck Library
interface Duck {
fun quack()
fun swim()
}
class MyClass: MyType {
override fun g() = trace("g()")
override fun h() = trace("h()")
class RealDuck : Duck {
override fun quack() = trace("quack")
override fun swim() = trace("swim")
}
fun useMyType(mt: MyType) {
mt.g()
mt.h()
fun interactWithDuck(duck: Duck) {
duck.quack()
duck.swim()
}
class MyClassAdaptedForLib(
private val field: MyClass
) : LibType, MyType by field {
override fun f1() = field.h()
override fun f2() = field.g()
// Our codebase
interface Crocodile {
fun bite()
}
fun adapt(mc: MyClass) =
MyClassAdaptedForLib(mc)
class RealCrocodile : Crocodile {
override fun bite() = trace("Mnom-mnom")
}
fun interactWithCrocodile(crocodile: Crocodile) {
trace("Panic!!!")
crocodile.bite()
}
class IAmHonestlyDuck(
private val crocodile: Crocodile
) : Duck, Crocodile by crocodile {
override fun quack() = crocodile.bite()
override fun swim() = crocodile.bite()
}
fun mimicDuck(crocodile: Crocodile): IAmHonestlyDuck =
IAmHonestlyDuck(crocodile)
fun main() {
val mc = adapt(MyClass())
utility1(mc)
utility2(mc)
useMyType(mc)
val honestlyDuck = mimicDuck(RealCrocodile())
interactWithDuck(honestlyDuck)
interactWithCrocodile(honestlyDuck)
trace eq """
h()
g()
g()
h()
g()
h()
Mnom-mnom
Mnom-mnom
Panic!!!
Mnom-mnom
"""
}

View File

@ -2,5 +2,15 @@ type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 545
length: 7
placeholder_text: /* private */
- offset: 586
length: 24
placeholder_text: /* TODO */
- offset: 902
length: 12
placeholder_text: honestlyDuck.crocodile
- name: test/Tests.kt
visible: false

View File

@ -1,23 +1,15 @@
## Class Delegation (#2)
Exercise 3 in [Inheritance & Extensions] uses
composition to adapt `MyClass` to work with `UsefulLibrary`. This produces an
inconsistency when using `MyClass` with the `useMyClass()` function: the
composed `field` must be explicitly named during the call:
Exercise 3 in [Inheritance & Extensions](#inheritance-and-extensions) uses
composition to adapt `Crocodile` to work with `interactWithDuck`.
This produces an inconsistency when using `IAmHonestlyDuck` with the
`interactWithCrocodile()` function: the composed `crocodile` must be explicitly
named during the call:
```kotlin
useMyClass(mc.field)
interactWithCrocodile(honestlyDuck.crocodile)
```
Modify the solution to that exercise using class delegation so you can call a
function `useMyType(mc)`. Make the `field` argument to `MyClassAdaptedForLib`
`private` so you *cannot* expose `field`.
Because class delegation works with interfaces, you must first create an
interface `MyType` for `MyClass`. If you're using IntelliJ IDEA, you can do
this by right-clicking `MyClass`, selecting "Refactor," then choosing "Extract
Interface." Modify the rest of the code to use `MyType` whenever possible,
rather than `MyClass`, and rename `useMyClass()` to `useMyType()`.
Now modify `MyClassAdaptedForLib` so that `field` is `private` and is the
delegate for `MyType`.
function `interactWithCrocodile(honestlyDuck)`. Make the `crocodile` argument to
`IAmHonestlyDuck` `private` so you *cannot* expose `field`.