Modified ex 2 in class delegation
This commit is contained in:
parent
6e498e2ab6
commit
c6598943c9
|
@ -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
|
||||
"""
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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`.
|
Loading…
Reference in New Issue