From 27627f0ce4f044f4338e8dfaa5c7192e68cc82ae Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sun, 22 Mar 2020 16:01:40 +0100 Subject: [PATCH] Removed solutions from exercise descriptions --- .../Abstract Classes/Exercise 1/task.md | 34 +--- .../Abstract Classes/Exercise 2/task.md | 52 +----- .../Abstract Classes/Exercise 3/task.md | 70 +------- .../Exercise 1/task.md | 33 +--- .../Exercise 2/task.md | 78 +------- .../Exercise 3/task.md | 79 +-------- .../Class Delegation/Exercise 1/task.md | 50 +----- .../Class Delegation/Exercise 2/task.md | 52 +----- .../Class Delegation/Exercise 3/task.md | 64 +------ .../Companion Objects/Exercise 1/task.md | 65 +------ .../Companion Objects/Exercise 2/task.md | 77 +------- .../Companion Objects/Exercise 3/task.md | 83 +-------- .../Complex Constructors/Exercise 1/task.md | 20 +-- .../Complex Constructors/Exercise 2/task.md | 21 +-- .../Complex Constructors/Exercise 3/task.md | 25 +-- .../Composition/Exercise 1/task.md | 58 +----- .../Composition/Exercise 2/task.md | 62 +------ .../Composition/Exercise 3/task.md | 83 +-------- .../Downcasting/Exercise 1/task.md | 44 +---- .../Downcasting/Exercise 2/task.md | 15 +- .../Downcasting/Exercise 3/task.md | 65 +------ .../Exercise 1/task.md | 89 +--------- .../Exercise 2/task.md | 72 +------- .../Exercise 3/task.md | 47 +---- .../Inner Classes/Exercise 1/task.md | 42 +---- .../Inner Classes/Exercise 2/task.md | 26 +-- .../Inner Classes/Exercise 3/task.md | 64 +------ .../Nested Classes/Exercise 1/task.md | 59 +------ .../Nested Classes/Exercise 2/task.md | 65 +------ .../Nested Classes/Exercise 3/task.md | 62 +------ .../Nested Classes/Exercise 4/task.md | 62 +------ .../Object-Oriented Design/Exercise 1/task.md | 20 +-- .../Object-Oriented Design/Exercise 2/task.md | 94 +--------- .../Object-Oriented Design/Exercise 3/task.md | 74 +------- .../Objects/Exercise 1/task.md | 34 +--- .../Objects/Exercise 2/task.md | 37 +--- .../Objects/Exercise 3/task.md | 53 +----- .../Polymorphism/Exercise 1/task.md | 32 +--- .../Polymorphism/Exercise 2/task.md | 167 +----------------- .../Polymorphism/Exercise 3/task.md | 40 +---- .../Sealed Classes/Exercise 1/task.md | 67 +------ .../Sealed Classes/Exercise 2/task.md | 22 +-- .../Sealed Classes/Exercise 3/task.md | 25 +-- .../Upcasting/Exercise 1/task.md | 52 +----- .../Upcasting/Exercise 2/task.md | 59 +------ .../Upcasting/Exercise 3/task.md | 53 +----- 46 files changed, 46 insertions(+), 2501 deletions(-) diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 1/task.md b/Object-Oriented Programming/Abstract Classes/Exercise 1/task.md index 95766b28..2e77bb61 100644 --- a/Object-Oriented Programming/Abstract Classes/Exercise 1/task.md +++ b/Object-Oriented Programming/Abstract Classes/Exercise 1/task.md @@ -5,36 +5,4 @@ classes. Create an abstract class `WithParams` with class parameters `val i: Int` and `var s: String = ""`. Inherit a class `Concrete` from `WithParams`. Provide constructors for both that use `atomictest.Trace` to show the class name and arguments. Create an instance of `Concrete` and verify the order of -the constructor calls. - -```kotlin -// Abstract/AbsExercise1.kt -package abstractclasses -import atomictest.* - -private val trace = Trace() - -abstract class WithParams( - val i: Int, - var s: String = "" -) { - init { - trace("WithParams $i $s") - } -} - -class Concrete(i: Int, s: String): - WithParams(i, s) { - init { - trace("Concrete $i $s") - } -} - -fun main() { - Concrete(11, "One Louder") - trace eq """ - WithParams 11 One Louder - Concrete 11 One Louder - """ -} -``` \ No newline at end of file +the constructor calls. \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 2/task.md b/Object-Oriented Programming/Abstract Classes/Exercise 2/task.md index 1cd5c47c..9d7781d6 100644 --- a/Object-Oriented Programming/Abstract Classes/Exercise 2/task.md +++ b/Object-Oriented Programming/Abstract Classes/Exercise 2/task.md @@ -14,54 +14,4 @@ Add a function `tune()` that takes an `Instrument` parameter and plays that In `main()`, create an `orchestra` which is a `List` containing an instance of each type of `Instrument`. Call `tune()` for each `Instrument` in -the `orchestra`, and validate the results using `Trace`. - -```kotlin -// Abstract/AbsExercise2.kt -package abstractclasses2 -import atomictest.* - -private val trace = Trace() - -enum class Note { - A, B, C, D, E, F, G -} - -abstract class Instrument(val name: String) { - abstract fun play(n: Note) -} - -open class Wind : Instrument("Wind") { - override fun play(n: Note) { - trace("$name blow $n") - } -} - -class Percussion : Instrument("Percussion") { - override fun play(n: Note) { - trace("$name strike $n") - } -} - -class Stringed : Instrument("Stringed") { - override fun play(n: Note) { - trace("$name pluck $n") - } -} - -fun tune(i: Instrument) = i.play(Note.C) - -fun main() { - val orchestra = listOf( - Wind(), - Percussion(), - Stringed() - ) - orchestra.forEach { tune(it) } - trace eq """ - Wind blow C - Percussion strike C - Stringed pluck C - """ -} -``` \ No newline at end of file +the `orchestra`, and validate the results using `Trace`. \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 3/task.md b/Object-Oriented Programming/Abstract Classes/Exercise 3/task.md index d29ce401..29ef3ef5 100644 --- a/Object-Oriented Programming/Abstract Classes/Exercise 3/task.md +++ b/Object-Oriented Programming/Abstract Classes/Exercise 3/task.md @@ -4,72 +4,4 @@ Add classes to the previous example: `Bowed` inherits from `Stringed` and uses `bow` instead of `plucked` in the output, while `Brass` and `Reed` inherit from `Wind`. `Brass` and `Reed` do not override `play()`. Make the necessary modifications to allow each class to accept a `String` argument containing the -class name. - -```kotlin -// Abstract/AbsExercise3.kt -package abstractclasses3 -import atomictest.* - -private val trace = Trace() - -enum class Note { - A, B, C, D, E, F, G -} - -abstract class Instrument(val name: String) { - abstract fun play(n: Note) -} - -open class Wind(name: String? = null) : - Instrument(name ?: "Wind") { - override fun play(n: Note) { - trace("$name blow $n") - } -} - -open class Percussion(name: String? = null) : - Instrument(name ?: "Percussion") { - override fun play(n: Note) { - trace("$name strike $n") - } -} - -open class Stringed(name: String? = null) : - Instrument(name ?: "Stringed") { - override fun play(n: Note) { - trace("$name pluck $n") - } -} - -class Bowed : Stringed("Bowed") { - override fun play(n: Note) { - trace("$name bow $n") - } -} - -class Brass : Wind("Brass") -class Reed : Wind("Reed") - -fun tune(i: Instrument) = i.play(Note.C) - -fun main() { - val orchestra = listOf( - Wind(), - Percussion(), - Stringed(), - Bowed(), - Brass(), - Reed() - ) - orchestra.forEach { tune(it) } - trace eq """ - Wind blow C - Percussion strike C - Stringed pluck C - Bowed bow C - Brass blow C - Reed blow C - """ -} -``` \ No newline at end of file +class name. \ No newline at end of file diff --git a/Object-Oriented Programming/Base Class Initialization/Exercise 1/task.md b/Object-Oriented Programming/Base Class Initialization/Exercise 1/task.md index d4741564..90ea0847 100644 --- a/Object-Oriented Programming/Base Class Initialization/Exercise 1/task.md +++ b/Object-Oriented Programming/Base Class Initialization/Exercise 1/task.md @@ -5,35 +5,4 @@ compare a `Trace` object to a multiline `String`. Create a global `private` `val trace` initialized to `Trace()`. Create a class `A`; inside its `init`, and call `trace(className)` to append the name of the class to `trace`. Inherit `B` from `A` and `C` from `B`, and give them similar `init`s. Create -an instance of `C` to see the initialization order. - -```kotlin -// BaseClassInit/BCIExercise1.kt -package baseclassinit -import atomictest.* - -private val trace = Trace() - -open class A { - init { - trace("A") - } -} - -open class B : A() { - init { - trace("B") - } -} - -class C : B() { - init { - trace("C") - } -} - -fun main() { - C() - trace eq "A B C" -} -``` \ No newline at end of file +an instance of `C` to see the initialization order. \ No newline at end of file diff --git a/Object-Oriented Programming/Base Class Initialization/Exercise 2/task.md b/Object-Oriented Programming/Base Class Initialization/Exercise 2/task.md index be934e3a..b16d96cb 100644 --- a/Object-Oriented Programming/Base Class Initialization/Exercise 2/task.md +++ b/Object-Oriented Programming/Base Class Initialization/Exercise 2/task.md @@ -9,80 +9,4 @@ Create a class `Plate` and inherit `DinnerPlate` from it. Create a class `Custom` (as in "a cultural tradition"), and inherit `PlaceSetting` from it. Inside `PlaceSetting`, create properties containing `Spoon`, `Fork`, `Knife` and `DinnerPlate`, in that order. Create an instance of `PlaceSetting` to see -the initialization order. - -```kotlin -// BaseClassInit/BCIExercise2.kt -package baseclassinit -import atomictest.* - -private val trace = Trace() - -open class Plate { - init { - trace("Plate") - } -} - -class DinnerPlate : Plate() { - init { - trace("DinnerPlate") - } -} - -open class Utensil { - init { - trace("Utensil") - } -} - -class Spoon : Utensil() { - init { - trace("Spoon") - } -} - -class Fork : Utensil() { - init { - trace("Fork") - } -} - -class Knife : Utensil() { - init { - trace("Knife") - } -} - -open class Custom() { - init { - trace("Custom") - } -} - -class PlaceSetting : Custom() { - val spoon = Spoon() - val fork = Fork() - val knife = Knife() - val plate = DinnerPlate() - init { - trace("PlaceSetting") - } -} - -fun main() { - PlaceSetting() - trace eq """ - Custom - Utensil - Spoon - Utensil - Fork - Utensil - Knife - Plate - DinnerPlate - PlaceSetting - """ -} -``` \ No newline at end of file +the initialization order. \ No newline at end of file diff --git a/Object-Oriented Programming/Base Class Initialization/Exercise 3/task.md b/Object-Oriented Programming/Base Class Initialization/Exercise 3/task.md index 7046fb48..69018d8e 100644 --- a/Object-Oriented Programming/Base Class Initialization/Exercise 3/task.md +++ b/Object-Oriented Programming/Base Class Initialization/Exercise 3/task.md @@ -2,81 +2,4 @@ Modify the previous exercise so that every class has a class argument of `i: Int`, and add this to the end of the `String` in the call to `trace()` inside -each `init`. - -```kotlin -// BaseClassInit/BCIExercise3.kt -package baseclassinit -import atomictest.* - -private val trace = Trace() - -open class Plate1(i: Int) { - init { - trace("Plate $i") - } -} - -class DinnerPlate1(i: Int) : Plate1(i) { - init { - trace("DinnerPlate $i") - } -} - -open class Utensil1(i: Int) { - init { - trace("Utensil $i") - } -} - -class Spoon1(i: Int) : Utensil1(i) { - init { - trace("Spoon $i") - } -} - -class Fork1(i: Int) : Utensil1(i) { - init { - trace("Fork $i") - } -} - -class Knife1(i: Int) : Utensil1(i) { - init { - trace("Knife $i") - } -} - -// A cultural way of doing something: -open class Custom1(i: Int) { - init { - trace("Custom $i") - } -} - -class PlaceSetting1(i: Int) : Custom1(i) { - val spoon = Spoon1(i) - val fork = Fork1(i) - val knife = Knife1(i) - val plate = DinnerPlate1(i) - init { - trace("PlaceSetting $i") - } -} - -fun main() { - PlaceSetting1(9) - trace eq """ - Custom 9 - Utensil 9 - Spoon 9 - Utensil 9 - Fork 9 - Utensil 9 - Knife 9 - Plate 9 - DinnerPlate 9 - PlaceSetting 9 - """ -} -``` \ No newline at end of file +each `init`. \ No newline at end of file diff --git a/Object-Oriented Programming/Class Delegation/Exercise 1/task.md b/Object-Oriented Programming/Class Delegation/Exercise 1/task.md index 11ecaf22..252c5a5d 100644 --- a/Object-Oriented Programming/Class Delegation/Exercise 1/task.md +++ b/Object-Oriented Programming/Class Delegation/Exercise 1/task.md @@ -3,52 +3,4 @@ Modify `ModelingMI.kt` by adding `fun resize(scale: Int): Int` to `Rectangle`, which just returns `scale`. Add a `fun rightClicked(): Boolean` to `MouseManager`. Call the new functions in `main()` and verify that `Button` -needs no modifications to support the new interfaces. - -```kotlin -// ClassDelegation/ClassDelegEx1.kt -package classdelegationex1 -import atomictest.eq - -interface Rectangle { - fun paint(): Int - fun resize(scale: Int): Int -} - -class ButtonImage( - val width: Int, - val height: Int -) : Rectangle { - override fun paint() = width * height - override fun resize(scale: Int) = scale -} - -interface MouseManager { - fun clicked(): Boolean - fun hovering(): Boolean - fun rightClicked(): Boolean -} - -class UserInput : MouseManager { - override fun clicked() = true - override fun hovering() = true - override fun rightClicked() = true -} - -class Button( - val width: Int, - val height: Int, - val image: Rectangle = - ButtonImage(width, height), - val input: MouseManager = UserInput() -) : Rectangle by image, MouseManager by input - -fun main() { - val button = Button(10, 5) - button.paint() eq 50 - button.clicked() eq true - button.hovering() eq true - button.resize(10) eq 10 - button.rightClicked() eq true -} -``` \ No newline at end of file +needs no modifications to support the new interfaces. \ No newline at end of file diff --git a/Object-Oriented Programming/Class Delegation/Exercise 2/task.md b/Object-Oriented Programming/Class Delegation/Exercise 2/task.md index cfb3be53..6fc77e4b 100644 --- a/Object-Oriented Programming/Class Delegation/Exercise 2/task.md +++ b/Object-Oriented Programming/Class Delegation/Exercise 2/task.md @@ -20,54 +20,4 @@ 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`. - -```kotlin -// ClassDelegation/ClassDelegEx2.kt -package classdelegationex2 -import usefullibrary.* -import atomictest.* - -private val trace = Trace() - -interface MyType { - fun g() - fun h() -} - -class MyClass: MyType { - override fun g() = trace("g()") - override fun h() = trace("h()") -} - -fun useMyType(mt: MyType) { - mt.g() - mt.h() -} - -class MyClassAdaptedForLib( - private val field: MyClass -) : LibType, MyType by field { - override fun f1() = field.h() - override fun f2() = field.g() -} - -fun adapt(mc: MyClass) = - MyClassAdaptedForLib(mc) - -fun main() { - val library = UsefulLibrary() - val mc = adapt(MyClass()) - library.utility1(mc) - library.utility2(mc) - useMyType(mc) - trace eq """ - h() - g() - g() - h() - g() - h() - """ -} -``` \ No newline at end of file +delegate for `MyType`. \ No newline at end of file diff --git a/Object-Oriented Programming/Class Delegation/Exercise 3/task.md b/Object-Oriented Programming/Class Delegation/Exercise 3/task.md index 411250c2..19375b3a 100644 --- a/Object-Oriented Programming/Class Delegation/Exercise 3/task.md +++ b/Object-Oriented Programming/Class Delegation/Exercise 3/task.md @@ -23,66 +23,4 @@ Create a class `AA` that implements `A`, producing the value `1` for `x` and `z`, and tracing `"AA.u()"` for `u()` and `"AA.v()"` for `v()`. Create a similar implementation `BB` implementing `B`. Now create a class `Delegation` which delegates to both `A` and `B`. IntelliJ or the compiler will tell you -what you need to do to solve the collisions. - -```kotlin -// ClassDelegation/ClassDelegEx3.kt -package classdelegationex3 -import atomictest.* - -private val trace = Trace() - -interface A { - val x: Int - val z: Int - fun u() - fun v() -} - -interface B { - val y: Int - val z: Int - fun v() - fun w() -} - -class AA : A { - override val x = 1 - override val z = 1 - override fun u() = trace("AA.u()") - override fun v() = trace("AA.v()") -} - -class BB : B { - override val y = 1 - override val z = 1 - override fun v() = trace("BB.v()") - override fun w() = trace("BB.w()") -} - -class Delegation(val a: A, val b: B) : - A by a, B by b { - override val z = a.z + b.z - override fun v() { - trace("Delegation.v()") - a.v() - b.v() - trace("Delegation.z: $z") - } -} - -fun main() { - val d = Delegation(AA(), BB()) - d.u() - d.v() - d.w() - trace eq """ - AA.u() - Delegation.v() - AA.v() - BB.v() - Delegation.z: 2 - BB.w() - """ -} -``` \ No newline at end of file +what you need to do to solve the collisions. \ No newline at end of file diff --git a/Object-Oriented Programming/Companion Objects/Exercise 1/task.md b/Object-Oriented Programming/Companion Objects/Exercise 1/task.md index c8940123..60e39c5d 100644 --- a/Object-Oriented Programming/Companion Objects/Exercise 1/task.md +++ b/Object-Oriented Programming/Companion Objects/Exercise 1/task.md @@ -24,67 +24,4 @@ containing an anonymous inner class that implements `VendorFactory`. Now write a standalone function `consumer(factory: VendorFactory)` which uses `factory` to create a `Vendor`. Use that `Vendor` to call `pencil()` and -`pen()`. The starter code in `main()` will validate your solution. - -```kotlin -// CompanionObjects/CompanionEx1.kt -package companionobjectex1 -import atomictest.* - -private val trace = Trace() - -interface Vendor { - fun pencil() - fun pen() -} - -interface VendorFactory { - fun create(): Vendor -} - -class Vendor1 private constructor() : Vendor { - override fun pencil() { - trace("Vendor1 pencil") - } - override fun pen() { - trace("Vendor1 pen") - } - companion object { - var factory = object : VendorFactory { - override fun create() = Vendor1() - } - } -} - -class Vendor2 private constructor() : Vendor { - override fun pencil() { - trace("Vendor2 pencil") - } - override fun pen() { - trace("Vendor2 pen") - } - companion object { - var factory = object : VendorFactory { - override fun create() = Vendor2() - } - } -} - -fun consumer(factory: VendorFactory) { - val vendor = factory.create() - vendor.pencil() - vendor.pen() -} - -fun main() { - // Implementations are interchangeable: - consumer(Vendor1.factory) - consumer(Vendor2.factory) - trace eq """ - Vendor1 pencil - Vendor1 pen - Vendor2 pencil - Vendor2 pen - """ -} -``` \ No newline at end of file +`pen()`. The starter code in `main()` will validate your solution. \ No newline at end of file diff --git a/Object-Oriented Programming/Companion Objects/Exercise 2/task.md b/Object-Oriented Programming/Companion Objects/Exercise 2/task.md index 2d66f171..e0b40833 100644 --- a/Object-Oriented Programming/Companion Objects/Exercise 2/task.md +++ b/Object-Oriented Programming/Companion Objects/Exercise 2/task.md @@ -23,79 +23,4 @@ both `private` constructors with no arguments. Each class should contain a constructor. Each `companion object` contains a `const val max` which is used within `move()`. The definitions of `playGame()` and `main()` are provided; complete the code in `Checkers` and `Chess` so it satisfies the tests in -`main()`. - -```kotlin -// CompanionObjects/CompanionEx2.kt -package companionobjectex2 -import atomictest.* - -private val trace = Trace() - -interface BoardGame { - fun move(): Boolean - companion object { - fun createBoard() { - trace("BoardGame.createBoard()") - } - } -} - -interface GameFactory { - fun create(): BoardGame -} - -class -Checkers private constructor() : BoardGame { - private var moves = 0 - override fun move(): Boolean { - trace("Checkers move $moves") - return ++moves != max - } - companion object Factory : GameFactory { - private const val max = 3 - init { - BoardGame.createBoard() - } - override fun create() = Checkers() - } -} - -class -Chess private constructor() : BoardGame { - private var moves = 0 - override fun move(): Boolean { - trace("Chess move $moves") - return ++moves != max - } - companion object Factory : GameFactory { - private const val max = 4 - init { - BoardGame.createBoard() - } - override fun create() = Chess() - } -} - -fun playGame(factory: GameFactory) { - val s = factory.create() - while (s.move()) - ; -} - -fun main() { - playGame(Checkers.Factory) - playGame(Chess.Factory) - trace eq """ - BoardGame.createBoard() - Checkers move 0 - Checkers move 1 - Checkers move 2 - BoardGame.createBoard() - Chess move 0 - Chess move 1 - Chess move 2 - Chess move 3 - """ -} -``` \ No newline at end of file +`main()`. \ No newline at end of file diff --git a/Object-Oriented Programming/Companion Objects/Exercise 3/task.md b/Object-Oriented Programming/Companion Objects/Exercise 3/task.md index 1cd032b8..7e5b736e 100644 --- a/Object-Oriented Programming/Companion Objects/Exercise 3/task.md +++ b/Object-Oriented Programming/Companion Objects/Exercise 3/task.md @@ -55,85 +55,4 @@ steps during object creation. `applyForAccount()` begins the creation of a new the `Account`, and `completeAccount()` takes an `ID`, adds an account `number`, and moves the `Account` from the `applied` to the `accounts` list. -The starter code in `main()` will validate your solution. - -```kotlin -// CompanionObjects/CompanionEx3.kt -package companionobjectex3 -import kotlin.random.Random -import atomictest.* - -data class ID( - val name: String, - val id: String = idGenerator() -) { - companion object { - const val size = 10 - private val r = Random(47) - private val source = - ('a'..'z') + ('A'..'Z') + ('0'..'9') - private fun idGenerator() = - (1..size).map { source.random(r) } - .joinToString("") - fun test(n: Int) = List(n) { - ID(('a' + it).toString()) - }.joinToString(",\n") - } -} - -class Bank(val name: String) { - private val applied = - mutableListOf() - private val accounts = - mutableListOf() - private class Account(val name: String) { - var id: ID? = null - private var number: Long? = null - fun addID(verifiedID: ID) { - id = verifiedID - } - companion object Numbers { - private var i: Long = 1000 - private fun nextAccountNumber() = i++ - } - fun finish() { - number = nextAccountNumber() - } - override fun toString() = "$id $number" - } - fun applyForAccount(name: String) = - applied.add(Account(name)) - fun addID(id: ID) = applied - .first { it.name == id.name }.addID(id) - fun completeAccount(verifiedID: ID) { - val account = - applied.first { it.id == verifiedID } - account.finish() - accounts.add(account) - applied.remove(account) - } - override fun toString() = - accounts.joinToString("\n") -} - -fun main() { - ID.test(4) eq """ - ID(name=a, id=weazblk9UF), - ID(name=b, id=LCcPJtUGh5), - ID(name=c, id=Acs5BzSj6m), - ID(name=d, id=gHrshDvhwc) - """.trimIndent() - val bank = Bank("Jerry's Savings & Loan") - listOf(ID("Morty Smith"), ID("Beth Smith"), - ID("Summer Smith")).forEach { - bank.applyForAccount(it.name) - bank.addID(it) - bank.completeAccount(it) - } - bank eq """ - ID(name=Morty Smith, id=ePkc0HjTAU) 1000 - ID(name=Beth Smith, id=jjePlEO93w) 1001 - ID(name=Summer Smith, id=C8yaeFEgv6) 1002 - """.trimIndent() -} -``` \ No newline at end of file +The starter code in `main()` will validate your solution. \ No newline at end of file diff --git a/Object-Oriented Programming/Complex Constructors/Exercise 1/task.md b/Object-Oriented Programming/Complex Constructors/Exercise 1/task.md index 7a9ded42..a6875ef9 100644 --- a/Object-Oriented Programming/Complex Constructors/Exercise 1/task.md +++ b/Object-Oriented Programming/Complex Constructors/Exercise 1/task.md @@ -1,22 +1,4 @@ ## Complex Constructors (#1) Modify `Alien` by making `name` `private`, then giving it a constructor that -assigns its `name` to the `val` property `myName`. - -```kotlin -// ComplexConstructors/Exercise1.kt -package complexconstructors -import atomictest.eq - -class Alien2(private val name: String) { - val myName: String - init { - myName = name - } -} - -fun main() { - val alien = Alien2("Pencilvester") - alien.myName eq "Pencilvester" -} -``` \ No newline at end of file +assigns its `name` to the `val` property `myName`. \ No newline at end of file diff --git a/Object-Oriented Programming/Complex Constructors/Exercise 2/task.md b/Object-Oriented Programming/Complex Constructors/Exercise 2/task.md index 0be3c3a4..578e0201 100644 --- a/Object-Oriented Programming/Complex Constructors/Exercise 2/task.md +++ b/Object-Oriented Programming/Complex Constructors/Exercise 2/task.md @@ -3,23 +3,4 @@ Create a class called `SumChars` that takes `text: String` as a class argument. Add an un-initialized property `val sum: Int`. Inside `init`, define a local function `calc()` that sums up the integer values of each -of the characters in `text`. Call `calc()` and assign the result to `sum`. - -```kotlin -// ComplexConstructors/Exercise2.kt -package complexconstructors -import atomictest.eq - -class SumChars(text: String) { - val sum: Int - init { - fun calc() = - text.fold(0, {s, c -> s + c.toInt() }) - sum = calc() - } -} - -fun main() { - SumChars("What?").sum eq 467 -} -``` \ No newline at end of file +of the characters in `text`. Call `calc()` and assign the result to `sum`. \ No newline at end of file diff --git a/Object-Oriented Programming/Complex Constructors/Exercise 3/task.md b/Object-Oriented Programming/Complex Constructors/Exercise 3/task.md index fb037b41..1d517074 100644 --- a/Object-Oriented Programming/Complex Constructors/Exercise 3/task.md +++ b/Object-Oriented Programming/Complex Constructors/Exercise 3/task.md @@ -3,27 +3,4 @@ Show that multiple init sections are executed in declaration order. Create a class containing an uninitialized `var result: String`, then initialize `result` to `one two three` in three different `init` blocks. Note that -`result` cannot be a `val` in this case. - -```kotlin -// ComplexConstructors/Exercise3.kt -package complexconstructors -import atomictest.eq - -class MultipleInit() { - var result: String - init { - result = "one " - } - init { - result += "two " - } - init { - result += "three" - } -} - -fun main() { - MultipleInit().result eq "one two three" -} -``` \ No newline at end of file +`result` cannot be a `val` in this case. \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 1/task.md b/Object-Oriented Programming/Composition/Exercise 1/task.md index 462b7da5..3a3c5e07 100644 --- a/Object-Oriented Programming/Composition/Exercise 1/task.md +++ b/Object-Oriented Programming/Composition/Exercise 1/task.md @@ -1,60 +1,4 @@ ## Composition (#1) In `Car.kt`, add a `service()` member function to `Engine` and add a call to -this function in `main()`. - -```kotlin -// Composition/CompositionExercise1.kt -package compositionex1 -import atomictest.* - -private val trace = Trace() - -class Engine { - fun start() = trace("Engine start") - fun stop() = trace("Engine stop") - fun service() = trace("Engine service") -} - -class Wheel { - fun inflate(psi: Int) = - trace("Wheel inflate($psi)") -} - -class Window(val side: String) { - fun rollUp() = - trace("$side Window roll up") - fun rollDown() = - trace("$side Window roll down") -} - -class Door(val side: String) { - val window = Window(side) - fun open() = trace("$side Door open") - fun close() = trace("$side Door close") -} - -class Car { - val engine = Engine() - val wheel = List(4) { Wheel() } - // Two door: - val leftDoor = Door("left") - val rightDoor = Door("right") -} - -fun main() { - val car = Car() - car.leftDoor.open() - car.rightDoor.window.rollUp() - car.wheel[0].inflate(72) - car.engine.start() - car.engine.service() - trace eq """ - left Door open - right Window roll up - Wheel inflate(72) - Engine start - Engine service - """ -} -``` \ No newline at end of file +this function in `main()`. \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 2/task.md b/Object-Oriented Programming/Composition/Exercise 2/task.md index 4c3ed947..51e85a7f 100644 --- a/Object-Oriented Programming/Composition/Exercise 2/task.md +++ b/Object-Oriented Programming/Composition/Exercise 2/task.md @@ -7,64 +7,4 @@ classes, and a `List` and `List` to `House`. Create a `Bathroom`s called "Master", "Shared", and "Guest". Add `Bedroom`s called "Master", "Son", "Daughter", and "Guest". Use `atomictest.Trace` to capture all the class names and `name` properties as the `House` is constructed. Also -notice the order of construction. - -```kotlin -// Composition/CompositionExercise2.kt -package compositionex2 -import atomictest.* - -private val trace = Trace() - -open class Building(val name: String) { - init { trace("Building: $name") } -} - -class Kitchen(val name: String) { - init { trace("Kitchen: $name") } -} - -class Bedroom(val name: String) { - init { trace("Bedroom: $name") } -} - -class Bathroom(val name: String) { - init { trace("Bathroom: $name") } -} - -class House(name: String) : Building(name) { - val kitchens = listOf( - Kitchen("Main"), - Kitchen("Guest") - ) - val bathrooms = listOf( - Bathroom("Master"), - Bathroom("Shared"), - Bathroom("Guest") - ) - val bedrooms = listOf( - Bedroom("Master"), - Bedroom("Son"), - Bedroom("Daughter"), - Bedroom("Guest") - ) - init { trace("House: $name") } -} - -fun main() { - House("Our House") - trace eq """ - Building: Our House - Kitchen: Main - Kitchen: Guest - Bathroom: Master - Bathroom: Shared - Bathroom: Guest - Bedroom: Master - Bedroom: Son - Bedroom: Daughter - Bedroom: Guest - House: Our House - """ -} -``` \ No newline at end of file +notice the order of construction. \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 3/task.md b/Object-Oriented Programming/Composition/Exercise 3/task.md index 6894393c..1a6a42b7 100644 --- a/Object-Oriented Programming/Composition/Exercise 3/task.md +++ b/Object-Oriented Programming/Composition/Exercise 3/task.md @@ -18,85 +18,4 @@ you write: - `InMemory`, implemented with a `mutableMapOf()` - `Mock`, implemented with two `String` `var`s. -Write these classes so they pass the tests given in `main()`. - -```kotlin -// Composition/CompositionExercise3.kt -package compositionex3 -import atomictest.* - -private val trace = Trace() - -interface DataBase { - fun write(key: String, value: String) - fun read(key: String): String -} - -class NonRelational : DataBase { - private val db = - mutableListOf>() - override fun write( - key: String, value: String - ) { - db.add(Pair(key, value)) - } - override fun read(key: String) = - db.first { it.first == key }.second -} - -class InMemory : DataBase { - private val db = - mutableMapOf() - override fun write( - key: String, value: String - ) { - db[key] = value - } - override fun read(key: String) = - db[key] ?: "" -} - -class Mock : DataBase { - private var k = "" - private var v = "" - override fun write( - key: String, value: String - ) { k = key; v = value } - override fun read(key: String) = v -} - -class Holder(val db: DataBase) { - fun store(k: String, v: String) = - db.write(k, v) - fun fetch(k: String) = db.read(k) - private val data = """ - color: purple - dog: husky - art: deco - """.trimIndent().lines() - .map { it.split(": ") } - fun test() { - for(line in data) { - store(line[0], line[1]) - trace(fetch(line[0])) - } - } -} - -fun main() { - Holder(NonRelational()).test() - Holder(InMemory()).test() - Holder(Mock()).test() - trace eq """ - purple - husky - deco - purple - husky - deco - purple - husky - deco - """ -} -``` \ No newline at end of file +Write these classes so they pass the tests given in `main()`. \ No newline at end of file diff --git a/Object-Oriented Programming/Downcasting/Exercise 1/task.md b/Object-Oriented Programming/Downcasting/Exercise 1/task.md index edd7a1cf..f2344fea 100644 --- a/Object-Oriented Programming/Downcasting/Exercise 1/task.md +++ b/Object-Oriented Programming/Downcasting/Exercise 1/task.md @@ -7,46 +7,4 @@ function. The `trace` argument is the class name and function; for example Now write a function `checkAndCall(b: Base)` so that it calls the polymorphic member function, then uses a `when` to downcast and call the extended-interface -functions. - -```kotlin -// DownCasting/DownCastEx1.kt -package downcastingex1 -import atomictest.* - -private val trace = Trace() - -interface Base { - fun f() -} - -class Derived1 : Base { - override fun f() = trace("Derived1.f()") - fun g() = trace("Derived1.g()") -} - -class Derived2 : Base { - override fun f() = trace("Derived2.f()") - fun h() = trace("Derived2.h()") -} - -fun checkAndCall(b: Base) { - b.f() // Polymorphic call - when(b) { - is Derived1 -> b.g() - is Derived2 -> b.h() - } -} - -fun main() { - checkAndCall(Derived1()) // Upcast - checkAndCall(Derived2()) // Upcast - trace eq """ - Derived1.f() - Derived1.g() - Derived2.f() - Derived2.h() - """ -} - -``` \ No newline at end of file +functions. \ No newline at end of file diff --git a/Object-Oriented Programming/Downcasting/Exercise 2/task.md b/Object-Oriented Programming/Downcasting/Exercise 2/task.md index cb7ce77a..9b575c1c 100644 --- a/Object-Oriented Programming/Downcasting/Exercise 2/task.md +++ b/Object-Oriented Programming/Downcasting/Exercise 2/task.md @@ -9,17 +9,4 @@ There's a second, more dynamic form of `filterIsInstance()`, which takes a class object as a parameter. Pass `Dog::class.java` as the argument to `filterIsInstance()`, with the rest of the expression as described in the previous paragraph. How is this version of `filterIsInstance()` different from -the version that uses a generic argument? - -```kotlin -// DownCasting/DownCastEx2.kt -package downcasting -import atomictest.eq - -fun main() { - group.filterIsInstance() - .map(Dog::bark) eq "[Yip!, Yip!]" - group.filterIsInstance(Dog::class.java) - .map(Dog::bark) eq "[Yip!, Yip!]" -} -``` \ No newline at end of file +the version that uses a generic argument? \ No newline at end of file diff --git a/Object-Oriented Programming/Downcasting/Exercise 3/task.md b/Object-Oriented Programming/Downcasting/Exercise 3/task.md index ad6eac4d..1a59e3cc 100644 --- a/Object-Oriented Programming/Downcasting/Exercise 3/task.md +++ b/Object-Oriented Programming/Downcasting/Exercise 3/task.md @@ -14,67 +14,4 @@ Create a duplicate hierarchy from an interface `Animal2`, but in this case make `Beetle2`. In `main()`, create a `List` of `Animal2` objects and call `move()` for each one. -Compare the type-checked hierarchy to the polymorphic hierarchy. - -```kotlin -// DownCasting/DownCastEx3.kt -package downcastingex3 -import atomictest.* - -private val trace = Trace() - -interface Animal1 - -class Worm1: Animal1 { - fun wriggle() = trace("Wriggle") -} - -class Snail1: Animal1 { - fun slide() = trace("Slide") -} - -class Beetle1: Animal1 { - fun walk() = trace("Walk") -} - -fun move(a1: Animal1) { - when(a1) { - is Worm1 -> a1.wriggle() - is Snail1 -> a1.slide() - is Beetle1 -> a1.walk() - } -} - -interface Animal2 { - fun move() -} - -class Worm2: Animal2 { - override fun move() = trace("Wriggle") -} - -class Snail2: Animal2 { - override fun move() = trace("Slide") -} - -class Beetle2: Animal2 { - override fun move() = trace("Walk") -} - -fun main() { - val animals1 = - listOf(Worm1(), Snail1(), Beetle1()) - animals1.forEach { move(it) } - val animals2 = - listOf(Worm2(), Snail2(), Beetle2()) - animals2.forEach { it.move() } - trace eq """ - Wriggle - Slide - Walk - Wriggle - Slide - Walk - """ -} -``` \ No newline at end of file +Compare the type-checked hierarchy to the polymorphic hierarchy. \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task.md b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task.md index 5aeee182..9454d260 100644 --- a/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task.md +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task.md @@ -4,91 +4,4 @@ Following `AdjustTemp.kt`, add two extension functions `openWindow()` and `fan()` as ways of cooling. Add a class `DeltaTemperature2` where the extension functions are instead member functions, and an overloaded `adjust()` function which takes a `DeltaTemperature2`. Which approach seems better, or are they -about the same? - -```kotlin -// InheritanceExtensions/InhExtensionsEx1.kt -package inheritanceextensionsex1 - -import atomictest.* - -private val trace = Trace() - -class DeltaTemperature( - val current: Double, - val target: Double -) - -fun DeltaTemperature.heat() { - if (current < target) - trace("heating to $target") -} - -fun DeltaTemperature.cool() { - if (current > target) - trace("cooling to $target") -} - -fun DeltaTemperature.openWindow() { - if (current > target) - trace("cooling to $target") -} - -fun DeltaTemperature.fan() { - if (current > target) - trace("cooling to $target") -} - -class DeltaTemperature2( - val current: Double, - val target: Double -) { - fun heat() { - if (current < target) - trace("heating to $target") - } - fun cool() { - if (current > target) - trace("cooling to $target") - } - fun openWindow() { - if (current > target) - trace("cooling to $target") - } - fun fan() { - if (current > target) - trace("cooling to $target") - } -} - -fun adjust(deltaT: DeltaTemperature) { - deltaT.heat() - deltaT.cool() - deltaT.openWindow() - deltaT.fan() -} - -fun adjust(deltaT: DeltaTemperature2) { - deltaT.heat() - deltaT.cool() - deltaT.openWindow() - deltaT.fan() -} - -fun main() { - adjust(DeltaTemperature(60.0, 70.0)) - adjust(DeltaTemperature(80.0, 60.0)) - adjust(DeltaTemperature2(60.0, 70.0)) - adjust(DeltaTemperature2(80.0, 60.0)) - trace eq """ - heating to 70.0 - cooling to 60.0 - cooling to 60.0 - cooling to 60.0 - heating to 70.0 - cooling to 60.0 - cooling to 60.0 - cooling to 60.0 - """ -} -``` \ No newline at end of file +about the same? \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task.md b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task.md index 75243e56..64f0cacb 100644 --- a/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task.md +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task.md @@ -8,74 +8,4 @@ Refactor `BatteryPet2.kt` to improve the design: - You no longer need `Dog.sit()` - Change `playWithDog(dog: Dog)` to `playWithPet(pet: Pet)` - Add a `CatFood` type of `Energy`, and define the associated `Cat` class -- In `main()`, test all types of `Pet` - -```kotlin -// InheritanceExtensions/InhExtensionsEx2.kt -package inheritanceextensionsex2 -import atomictest.* - -private val trace = Trace() - -interface Energy { - fun replenish() = trace("Fill Bowl") -} - -open class Pet(open val energy: Energy) { - open fun speak() = trace("") - open fun settle() = trace("") - open fun feed() = energy.replenish() -} - -class DogFood : Energy - -open class Dog : Pet(DogFood()) { - override fun speak() = trace("Bark!") - override fun settle() = trace("Sitting...") -} - -class CatFood : Energy - -open class Cat : Pet(CatFood()) { - override fun speak() = trace("Meow!") - override fun settle() = - trace("In my basket...") -} - -class Batteries : Energy { - override fun replenish() = - trace("Change batteries") -} - -class ToyDog: Dog() { - override val energy = Batteries() -} - -fun play(pet: Pet) = pet.speak() - -fun playWithPet(pet: Pet) { - play(pet) - pet.settle() - pet.energy.replenish() -} - -fun main() { - val dog1 = Dog() - val dog2 = ToyDog() - val cat = Cat() - playWithPet(dog1) - playWithPet(dog2) - playWithPet(cat) - trace eq """ - Bark! - Sitting... - Fill Bowl - Bark! - Sitting... - Change batteries - Meow! - In my basket... - Fill Bowl - """ -} -``` \ No newline at end of file +- In `main()`, test all types of `Pet` \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task.md b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task.md index 6678de55..360403fd 100644 --- a/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task.md +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task.md @@ -4,49 +4,4 @@ Starting with `Adapter.kt` and `ComposeAdapter.kt`, create a function which dynamically adapts an object, accepting a `MyClass` and returning a `MyClassAdaptedForLib`. Is it possible to use the inheritance approach in `Adapter.kt`, or are you forced to use composition? (We'll revisit this issue -in [Class Delegation]). - -```kotlin -// InheritanceExtensions/InhExtensionsEx3.kt -package inheritanceextensionsex3 -import usefullibrary.* -import atomictest.* - -private val trace = Trace() - -class MyClass { - fun g() = trace("g()") - fun h() = trace("h()") -} - -fun useMyClass(mc: MyClass) { - mc.g() - mc.h() -} - -class MyClassAdaptedForLib( - val field: MyClass -) : LibType { - override fun f1() = field.h() - override fun f2() = field.g() -} - -fun adapt(mc: MyClass) = - MyClassAdaptedForLib(mc) - -fun main() { - val library = UsefulLibrary() - val mc = adapt(MyClass()) - library.utility1(mc) - library.utility2(mc) - useMyClass(mc.field) - trace eq """ - h() - g() - g() - h() - g() - h() - """ -} -``` \ No newline at end of file +in [Class Delegation]). \ No newline at end of file diff --git a/Object-Oriented Programming/Inner Classes/Exercise 1/task.md b/Object-Oriented Programming/Inner Classes/Exercise 1/task.md index bb92e73d..6d4042b1 100644 --- a/Object-Oriented Programming/Inner Classes/Exercise 1/task.md +++ b/Object-Oriented Programming/Inner Classes/Exercise 1/task.md @@ -2,44 +2,4 @@ Add a `hamster()` member function to `LocalInnerClasses.kt` with a local `val poke = "Squeak"` which returns an object of an anonymous inner class that -extends `Pet`, with a `speak()` that produces `poke + home()`. - -```kotlin -// InnerClasses/InnerEx1.kt -package innerclassesex1 -import atomictest.eq - -interface Pet { - fun speak(): String -} - -class PetCreator { - fun home() = " home!" - fun dog(): Pet { - val say = "Bark" - class Dog : Pet { - override fun speak() = say + home() - } - return Dog() - } - fun cat(): Pet { - val emit = "Meow" - return object : Pet { - override fun speak() = emit + home() - } - } - fun hamster(): Pet { - val poke = "Squeak" - return object : Pet { - override fun speak() = poke + home() - } - } -} - -fun main() { - val create = PetCreator() - create.dog().speak() eq "Bark home!" - create.cat().speak() eq "Meow home!" - create.hamster().speak() eq "Squeak home!" -} -``` \ No newline at end of file +extends `Pet`, with a `speak()` that produces `poke + home()`. \ No newline at end of file diff --git a/Object-Oriented Programming/Inner Classes/Exercise 2/task.md b/Object-Oriented Programming/Inner Classes/Exercise 2/task.md index ff2086f9..80f33e73 100644 --- a/Object-Oriented Programming/Inner Classes/Exercise 2/task.md +++ b/Object-Oriented Programming/Inner Classes/Exercise 2/task.md @@ -15,28 +15,4 @@ function `f()` which returns `"Any-based"`. Add a member function `manifest()` which produces a `String` containing the properties `contains` and `label` and the output of `f()`. The starter code in -`main()` will test your solution. - -```kotlin -// InnerClasses/InnerEx2.kt -package innerclassesex2 -import atomictest.eq - -class Box(contains: String, label: String) { - inner class Contents(val contains: String) - inner class Destination(val label: String) - private val contents = Contents(contains) - private val destination = Destination(label) - private val x = object : Any() { - fun f() = "Any-based" - } - fun manifest() = - "${contents.contains}: " + - "${destination.label} ${x.f()}" -} - -fun main() { - Box("Computer", "Tasmania").manifest() eq - "Computer: Tasmania Any-based" -} -``` \ No newline at end of file +`main()` will test your solution. \ No newline at end of file diff --git a/Object-Oriented Programming/Inner Classes/Exercise 3/task.md b/Object-Oriented Programming/Inner Classes/Exercise 3/task.md index fef99653..26bba55a 100644 --- a/Object-Oriented Programming/Inner Classes/Exercise 3/task.md +++ b/Object-Oriented Programming/Inner Classes/Exercise 3/task.md @@ -27,66 +27,4 @@ Now make `Container` inherit from `Iterable`, and add a function called from `Iterator`. Add a standalone function ` traceAll2(ib: Iterable)` that produces the same behavior as `traceAll()`. -The starter code contains a `main()` with tests to verify your code. - -```kotlin -// InnerClasses/InnerEx3.kt -package innerclassesex3 -import atomictest.* - -interface Selector { - fun end(): Boolean - fun current(): T - fun next() -} - -class Container( - iterable: Iterable -) : Iterable { - private val items = iterable.toMutableList() - fun add(x: T) = items.add(x) - fun selector() = object : Selector { - private var i = 0 - override fun end() = i == items.size - override fun current() = items[i] - override fun next() { - if (i < items.size) i++ - } - } - override - fun iterator() = object : Iterator { - private var i = 0 - override fun hasNext() = i < items.size - override fun next(): T = items[i++] - } -} - -fun traceAll(select: Selector): Trace { - val trace = Trace() - while (!select.end()) { - trace("${select.current()}") - select.next() - } - return trace -} - -fun traceAll2(ib: Iterable): Trace { - val trace = Trace() - val iter = ib.iterator() - while (iter.hasNext()) - trace("${iter.next()}") - return trace -} - -fun main() { - traceAll(Container(0..9).selector()) eq - "0 1 2 3 4 5 6 7 8 9" - traceAll2(Container(0..9)) eq - "0 1 2 3 4 5 6 7 8 9" - traceAll(Container(List(10){ it * it }) - .selector()) eq - "0 1 4 9 16 25 36 49 64 81" - traceAll2(Container(List(10){ it * it })) eq - "0 1 4 9 16 25 36 49 64 81" -} -``` \ No newline at end of file +The starter code contains a `main()` with tests to verify your code. \ No newline at end of file diff --git a/Object-Oriented Programming/Nested Classes/Exercise 1/task.md b/Object-Oriented Programming/Nested Classes/Exercise 1/task.md index 398e4bff..148473d0 100644 --- a/Object-Oriented Programming/Nested Classes/Exercise 1/task.md +++ b/Object-Oriented Programming/Nested Classes/Exercise 1/task.md @@ -5,61 +5,4 @@ In `FillIt.kt`, `State` is only used to determine when there are no more returning a `Boolean` from `turn()`. Once you have that working, add a third player by changing `enum class Mark { BLANK, X ,O }` to `enum class Mark { BLANK, X, Y, Z }`. In `turn()`, use a `when` expression to move to the next -`player` value. - -```kotlin -// NestedClasses/NestedEx1.kt -package nestedclassesex1 -import atomictest.* -import nestedclassesex1.Game.Mark.* -import java.lang.IllegalStateException -import kotlin.random.Random - -interface Game { - enum class Mark { BLANK, X, Y, Z } -} - -class FillIt( - val side: Int = 3, randomSeed: Int = 0 -) : Game { - val rand = Random(randomSeed) - private var grid = - MutableList(side * side) { BLANK } - private var player = X - fun turn(): Boolean { - val blanks = grid.withIndex() - .filter { it.value == BLANK } - if (blanks.isEmpty()) - return false - grid[blanks.random(rand).index] = player - player = when(player) { - BLANK -> throw IllegalStateException() - X -> Y - Y -> Z - Z -> X - } - return true - } - fun play() { - while(turn()) - ; - } - override fun toString() = - grid.chunked(side).joinToString("\n") -} - -fun main() { - val game = FillIt(8, 17) - game.play() - game eq """ - [X, Z, Y, Z, Z, Y, X, Y] - [Y, Z, Z, Y, Z, Y, Y, Z] - [Z, Y, Z, Y, Y, X, X, Y] - [X, X, X, Y, Y, X, X, Y] - [X, X, Z, X, Z, X, X, X] - [Z, X, Z, X, Y, Z, Z, Z] - [Y, Y, X, Y, Z, Z, Z, X] - [Y, X, Z, Y, Y, X, X, Z] - """.trimIndent() -} -``` \ No newline at end of file +`player` value. \ No newline at end of file diff --git a/Object-Oriented Programming/Nested Classes/Exercise 2/task.md b/Object-Oriented Programming/Nested Classes/Exercise 2/task.md index f084234f..0736ff93 100644 --- a/Object-Oriented Programming/Nested Classes/Exercise 2/task.md +++ b/Object-Oriented Programming/Nested Classes/Exercise 2/task.md @@ -1,67 +1,4 @@ ## Nested Classes (#2) In `NestedHouse.kt`, add two `Drawer`s to `Closet` and a `Bathtub` to -`Bathroom`. - -```kotlin -// NestedClasses/NestedEx2.kt -package nestedclassesex2 -import atomictest.* - -abstract class Cleanable(val id: String) { - open val parts: List = listOf() - fun clean(): String = - "${parts.map(Cleanable::clean)} $id clean\n" -} - -class House: Cleanable("House") { - override val parts = listOf( - Bedroom("Master Bedroom"), - Bedroom("Guest Bedroom") - ) - class Bedroom(id: String): Cleanable(id) { - override val parts = - listOf(Closet(), Bathroom()) - class Closet: Cleanable("Closet") { - override val parts = listOf( - Shelf(), Shelf(), Drawer(), Drawer() - ) - class Shelf: Cleanable("Shelf") - class Drawer: Cleanable("Drawer") - } - class Bathroom: Cleanable("Bathroom") { - override val parts = - listOf(Toilet(), Sink(), Bathtub()) - class Toilet: Cleanable("Toilet") - class Sink: Cleanable("Sink") - class Bathtub: Cleanable("Bathtub") - } - } -} - -fun main() { - House().clean().trim() eq """ - [[[[] Shelf clean - , [] Shelf clean - , [] Drawer clean - , [] Drawer clean - ] Closet clean - , [[] Toilet clean - , [] Sink clean - , [] Bathtub clean - ] Bathroom clean - ] Master Bedroom clean - , [[[] Shelf clean - , [] Shelf clean - , [] Drawer clean - , [] Drawer clean - ] Closet clean - , [[] Toilet clean - , [] Sink clean - , [] Bathtub clean - ] Bathroom clean - ] Guest Bedroom clean - ] House clean - """.trimIndent() -} -``` \ No newline at end of file +`Bathroom`. \ No newline at end of file diff --git a/Object-Oriented Programming/Nested Classes/Exercise 3/task.md b/Object-Oriented Programming/Nested Classes/Exercise 3/task.md index db50c3c9..afd0cbb4 100644 --- a/Object-Oriented Programming/Nested Classes/Exercise 3/task.md +++ b/Object-Oriented Programming/Nested Classes/Exercise 3/task.md @@ -1,64 +1,4 @@ ## Nested Classes (#3) "Unpack" the nested classes in `NestedHouse.kt` by turning each nested class -into a global class. - -``` -// NestedClasses/NestedEx3.kt -package nestedclassesex3 -import atomictest.* - -abstract class Cleanable(val id: String) { - open val parts: List = listOf() - fun clean(): String = - "${parts.map(Cleanable::clean)} $id clean\n" -} - -class Shelf : Cleanable("Shelf") - -class Closet : Cleanable("Closet") { - override val parts = - listOf(Shelf(), Shelf()) -} - -class Toilet : Cleanable("Toilet") - -class Sink : Cleanable("Sink") - -class Bathroom : Cleanable("Bathroom") { - override val parts = - listOf(Toilet(), Sink()) -} - -class Bedroom(id: String) : Cleanable(id) { - override val parts = - listOf(Closet(), Bathroom()) -} - -class House : Cleanable("House") { - override val parts = listOf( - Bedroom("Master Bedroom"), - Bedroom("Guest Bedroom") - ) -} - -fun main() { - Trace(House().clean()) eq """ - [[[[] Shelf clean - , [] Shelf clean - ] Closet clean - , [[] Toilet clean - , [] Sink clean - ] Bathroom clean - ] Master Bedroom clean - , [[[] Shelf clean - , [] Shelf clean - ] Closet clean - , [[] Toilet clean - , [] Sink clean - ] Bathroom clean - ] Guest Bedroom clean - ] House clean - """ -} -``` \ No newline at end of file +into a global class. \ No newline at end of file diff --git a/Object-Oriented Programming/Nested Classes/Exercise 4/task.md b/Object-Oriented Programming/Nested Classes/Exercise 4/task.md index 312a535a..11d61b7b 100644 --- a/Object-Oriented Programming/Nested Classes/Exercise 4/task.md +++ b/Object-Oriented Programming/Nested Classes/Exercise 4/task.md @@ -10,64 +10,4 @@ for each `Seat` type. `Seat` contains `abstract` member functions for `upgrade()` and `meal()` functions which forward their actions to the `Seat` object. -Bonus (Challenging): Why can't you use delegation for `seat` in `Ticket`? - -```kotlin -// NestedClasses/NestedEx4.kt -package nestedclassesex4 -import atomictest.eq -import nestedclassesex4.Seat.* - -abstract class Seat { - abstract fun upgrade(): Seat - abstract fun meal(): String - override fun toString() = - "${this::class.simpleName}" - class Coach : Seat() { - override fun upgrade() = Premium() - override fun meal() = "Bag Meal" - } - class Premium : Seat() { - override fun upgrade() = Business() - override fun meal() = "Bag Meal + Cookie" - } - class Business : Seat() { - override fun upgrade() = First() - override fun meal() = "Hot Meal" - } - class First : Seat() { - override fun upgrade() = First() - override fun meal() = "Private Chef" - } -} - -class Ticket( - private var seat: Seat = Coach() -) { - fun upgrade(): Seat { - seat = seat.upgrade() - return seat - } - fun meal() = seat.meal() - override fun toString() = "$seat" -} - -fun main() { - val tickets = listOf( - Ticket(), - Ticket(Premium()), - Ticket(Business()), - Ticket(First()) - ) - tickets.map(Ticket::meal) eq - "[Bag Meal, Bag Meal + Cookie, " + - "Hot Meal, Private Chef]" - tickets.map(Ticket::upgrade) eq - "[Premium, Business, First, First]" - tickets eq - "[Premium, Business, First, First]" - tickets.map(Ticket::meal) eq - "[Bag Meal + Cookie, Hot Meal, " + - "Private Chef, Private Chef]" -} -``` \ No newline at end of file +Bonus (Challenging): Why can't you use delegation for `seat` in `Ticket`? \ No newline at end of file diff --git a/Object-Oriented Programming/Object-Oriented Design/Exercise 1/task.md b/Object-Oriented Programming/Object-Oriented Design/Exercise 1/task.md index ef1af6e3..c542a060 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Exercise 1/task.md +++ b/Object-Oriented Programming/Object-Oriented Design/Exercise 1/task.md @@ -3,22 +3,4 @@ Add new type of `Actor` called `Bomb`, with `*` as its `symbol`. When it encounters a `Bomb`, the `Robot` loses all its energy and the `Bomb` disappears from the room (so the `Robot` still enters the room where the `Bomb` was). Add -one or more `*` to `stringMaze` to test your solution. - -SOLUTION:: - -Add the following to `Actors.kt`: - -```kotlin -class Bomb( - override val room: Room = Room() -) : Actor() { - override val symbol = '*' - override fun makeActor(r: Room) = Bomb(r) - override fun interact(robot: Robot): Room { - robot.energy = 0 // Bomb erases energy - room.actor = Empty(room) - return room - } -} -``` \ No newline at end of file +one or more `*` to `stringMaze` to test your solution. \ No newline at end of file diff --git a/Object-Oriented Programming/Object-Oriented Design/Exercise 2/task.md b/Object-Oriented Programming/Object-Oriented Design/Exercise 2/task.md index f653a7b6..ef470056 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Exercise 2/task.md +++ b/Object-Oriented Programming/Object-Oriented Design/Exercise 2/task.md @@ -8,96 +8,4 @@ Calculate the allocated number of moves by counting all the `Food` items in the maze, dividing by two and adding 50. The goal of the player is to reach the end of the maze before running out of -moves while maximizing the `energy` value. - -SOLUTION:: - -```kotlin -// ObjectOrientedDesign/OODesignEx2.kt -package oodesign -import org.hexworks.zircon.api.* -import org.hexworks.zircon.api.application.* -import org.hexworks.zircon.api.data.* -import org.hexworks.zircon.api.uievent.* -import org.hexworks.zircon.api.graphics.* -import org.hexworks.zircon.api.color.* - -fun robotExplorer2(stage: Stage) { - var moves = stage.maze - .filter { it == '.' }.length / 2 + 50 - val style = StyleSet.defaultStyle() - // Turn a character into a Tile: - fun charTile(c: Char, s: StyleSet = style) = - Tile.createCharacterTile(c, s) - // Initialize the zircon terminal emulator: - val grid = SwingApplications - .startTileGrid(AppConfig.newBuilder() - .withDefaultTileset( - TrueTypeFontResources.ubuntuMono(25)) - .withSize(Size.create( - stage.width, stage.height + 1)) - .build()) - // Strip newlines and create an iterator: - val maze = stage.maze - .filter { it != '\n' }.iterator() - // Fill the grid with the maze: - grid.size.fetchPositions().forEach { - if (maze.hasNext()) - grid.putTile(charTile(maze.next())) - } - // The robot's location as a Position: - fun robotPosition() = Position.create( - stage.robot.room.col, - stage.robot.room.row) - // Create the red robot icon layer: - val robotIcon = Layer.newBuilder() - .withSize(Size.one()) - .withOffset(robotPosition()) - .build().apply { - fill(charTile(stage.robot.symbol, - style.withForegroundColor( - ANSITileColor.RED))) - } - // As a layer, it can be moved around: - grid.addLayer(robotIcon) - // Update the character beneath the robot: - fun updateSymbolAtRobot() { - grid.cursorPosition = robotPosition() - grid.putTile( - charTile(stage.robot.room.actor.id())) - } - // Put a string on the blank bottom line: - fun console(s: String) { - grid.cursorPosition = - Position.create(1, stage.height + 1) - s.forEach { grid.putTile(charTile(it)) } - } - // Move the robot and update the screen: - fun robotGo(urge: Urge) { - moves-- - updateSymbolAtRobot() - stage.robot.move(urge) - robotIcon.moveTo(robotPosition()) - console( - "Energy: ${stage.robot.energy} " + - "Moves Remaining: $moves " - ) - } - // Respond to the keyboard arrow keys: - grid.processKeyboardEvents( - KeyboardEventType.KEY_PRESSED - ) { event, _ -> - when (event.code) { - KeyCode.UP -> robotGo(Urge.North) - KeyCode.DOWN -> robotGo(Urge.South) - KeyCode.LEFT -> robotGo(Urge.West) - KeyCode.RIGHT -> robotGo(Urge.East) - else -> Pass - } - } -} - -fun main() { - robotExplorer2(Stage(stringMaze)) -} -``` \ No newline at end of file +moves while maximizing the `energy` value. \ No newline at end of file diff --git a/Object-Oriented Programming/Object-Oriented Design/Exercise 3/task.md b/Object-Oriented Programming/Object-Oriented Design/Exercise 3/task.md index ddf09a2e..cd4aabb4 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Exercise 3/task.md +++ b/Object-Oriented Programming/Object-Oriented Design/Exercise 3/task.md @@ -24,76 +24,4 @@ class House( } ``` -Make your code satisfy the tests in `main()`. - -SOLUTION:: - -```kotlin -// ObjectOrientedDesign/OODesignEx3.kt -package oodesignex3 -import atomictest.* - -private val trace = Trace() - -interface TalkingAnimal { - fun create(): TalkingAnimal - fun speak() = - trace("I'm a ${this::class.simpleName}") -} - -class Monkey : TalkingAnimal { - override fun create() = Monkey() -} - -class Giraffe : TalkingAnimal { - override fun create() = Giraffe() - override fun speak() { - super.speak() - trace("The view is great up here!") - } -} - -class Hyena : TalkingAnimal { - override fun create() = Hyena() - override fun speak() { - super.speak() - trace("Yip Yip Yip!") - } -} - -class House( - val prototype: TalkingAnimal, - val size: Int -) { - val name: String = - "${prototype::class.simpleName} House" - val denizens: List = - List(size) { - prototype.create() - } - fun report() { - trace(name) - denizens.forEach { it.speak() } - } -} - -fun main() { - House(Giraffe(), 1).report() - House(Hyena(), 2).report() - House(Monkey(), 3).report() - trace eq """ - Giraffe House - I'm a Giraffe - The view is great up here! - Hyena House - I'm a Hyena - Yip Yip Yip! - I'm a Hyena - Yip Yip Yip! - Monkey House - I'm a Monkey - I'm a Monkey - I'm a Monkey - """ -} -``` \ No newline at end of file +Make your code satisfy the tests in `main()`. \ No newline at end of file diff --git a/Object-Oriented Programming/Objects/Exercise 1/task.md b/Object-Oriented Programming/Objects/Exercise 1/task.md index 1eba47a4..db2504c2 100644 --- a/Object-Oriented Programming/Objects/Exercise 1/task.md +++ b/Object-Oriented Programming/Objects/Exercise 1/task.md @@ -4,36 +4,4 @@ Create a file-level `private fun f()` and `private val p`. The starter code in `main()` will show you how to write these. Now duplicate `f()` and `p` inside `object Space` and again in `private object Space2`, and get these to work according to the code in `main()`. Notice the changes you need to make so that -`f()` is available in `main()`. Compare the different approaches. - -```kotlin -// Objects/ObjectEx1.kt -package objectex1 -import atomictest.* - -private val trace = Trace() - -private fun f() = trace("f() $p") -private val p = "p" - -object Space { - fun f() = trace("Space.f() $p") - private val p = "Space.p" -} - -private object Space2 { - fun f() = trace("Space2.f() $p") - private val p = "Space2.p" -} - -fun main() { - f() - Space.f() - Space2.f() - trace eq """ - f() p - Space.f() Space.p - Space2.f() Space2.p - """ -} -``` \ No newline at end of file +`f()` is available in `main()`. Compare the different approaches. \ No newline at end of file diff --git a/Object-Oriented Programming/Objects/Exercise 2/task.md b/Object-Oriented Programming/Objects/Exercise 2/task.md index be192aa9..923cfae6 100644 --- a/Object-Oriented Programming/Objects/Exercise 2/task.md +++ b/Object-Oriented Programming/Objects/Exercise 2/task.md @@ -3,39 +3,4 @@ Add more nesting to `ObjectNesting.kt`. Inside both the `Nested` objects, add another `Nested` object that looks the same as its enclosing `Nested`, with the same name and property, and an appropriate `String` for `a`. The code in -`main()` provides tests. Notice how the namespaces work. - -```kotlin -// Objects/ObjectEx2.kt -package objectex2 -import atomictest.eq - -object Outer { - object Nested { - val a = "Outer.Nested.a" - object Nested { - val a = "Outer.Nested.Nested.a" - } - } -} - -class HasObject { - object Nested { - val a = "HasObject.Nested.a" - object Nested { - val a = "HasObject.Nested.Nested.a" - } - } -} - -fun main() { - Outer.Nested.a eq - "Outer.Nested.a" - HasObject.Nested.a eq - "HasObject.Nested.a" - Outer.Nested.Nested.a eq - "Outer.Nested.Nested.a" - HasObject.Nested.Nested.a eq - "HasObject.Nested.Nested.a" -} -``` \ No newline at end of file +`main()` provides tests. Notice how the namespaces work. \ No newline at end of file diff --git a/Object-Oriented Programming/Objects/Exercise 3/task.md b/Object-Oriented Programming/Objects/Exercise 3/task.md index 79f4ae4c..113cefbc 100644 --- a/Object-Oriented Programming/Objects/Exercise 3/task.md +++ b/Object-Oriented Programming/Objects/Exercise 3/task.md @@ -19,55 +19,4 @@ that returns their class name. Now define an `object MonkeysVsSnakes` which is an `AdventureGame`, using the various `create()` functions to initialize it. `populate()` only needs to add -one `Monkey` and one `Snake`. The predefined `main()` will test your code. - -```kotlin -// Objects/ObjectEx3.kt -package objectex3 -import atomictest.* - -interface AdventureGame { - interface Environment - interface Character - val environment: Environment - val characters: MutableList - fun populate() -} - -class Jungle : AdventureGame.Environment { - object Factory { - fun create() = Jungle() - } -} - -class Monkey : AdventureGame.Character { - object Factory { - fun create() = Monkey() - } - override fun toString() = "Monkey" -} - -class Snake : AdventureGame.Character { - object Factory { - fun create() = Snake() - } - override fun toString() = "Snake" -} - -object MonkeysVsSnakes : AdventureGame { - override val environment = - Jungle.Factory.create() - override val characters = - mutableListOf() - override fun populate() { - characters.add(Monkey.Factory.create()) - characters.add(Snake.Factory.create()) - } -} - -fun main() { - MonkeysVsSnakes.populate() - MonkeysVsSnakes.characters eq - "[Monkey, Snake]" -} -``` \ No newline at end of file +one `Monkey` and one `Snake`. The predefined `main()` will test your code. \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 1/task.md b/Object-Oriented Programming/Polymorphism/Exercise 1/task.md index 841a0887..6b7acfd6 100644 --- a/Object-Oriented Programming/Polymorphism/Exercise 1/task.md +++ b/Object-Oriented Programming/Polymorphism/Exercise 1/task.md @@ -1,33 +1,3 @@ ## Polymorphism (#1) -Add `Hamster` (which says "Squeak!") to `Pet.kt`. - -```kotlin -// Polymorphism/PolyExercise1.kt -package polymorphismex1 -import atomictest.eq - -open class Pet { - open fun speak() = "Pet" -} - -class Dog : Pet() { - override fun speak() = "Bark!" -} - -class Cat : Pet() { - override fun speak() = "Meow" -} - -class Hamster : Pet() { - override fun speak() = "Squeak!" -} - -fun talk(pet: Pet) = pet.speak() - -fun main() { - talk(Dog()) eq "Bark!" - talk(Cat()) eq "Meow" - talk(Hamster()) eq "Squeak!" -} -``` \ No newline at end of file +Add `Hamster` (which says "Squeak!") to `Pet.kt`. \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 2/task.md b/Object-Oriented Programming/Polymorphism/Exercise 2/task.md index 7c938d3a..0c241692 100644 --- a/Object-Oriented Programming/Polymorphism/Exercise 2/task.md +++ b/Object-Oriented Programming/Polymorphism/Exercise 2/task.md @@ -2,169 +2,4 @@ Add `Wizard`, which implements `Magician`, and `Goblin` which implements `Fighter`, to `FantasyGame.kt`. In `main()`, create and test a `Wizard` named -"Max" and a `Goblin` named "Gorbag." - -```kotlin -// Polymorphism/PolyExercise2.kt -package polymorphismex2 -import atomictest.* - -private val trace = Trace() - -interface Character { - val name: String - val type: String - fun skills(): String - fun play() { - trace("$name $type:\n ${skills()}") - } -} - -interface Magician { - fun skills() = "Magic" -} - -interface Fighter { - fun skills() = "Fighting" -} - -interface Flyer { - fun skills() = "Flying" -} - -open class Elf(override val name: String) : - Character, Magician, Flyer { - override val type = "Elf" - override fun skills() = - super.skills() + ", " + - super.skills() -} - -class FightingElf(name: String) : - Elf(name), Fighter { - override val type = "FightingElf" - override fun skills() = - super.skills() + ", " + - super.skills() -} - -class Warrior(override val name: String) : - Character, Fighter { - override val type = "Warrior" - override fun skills() = super.skills() -} - -class Dragon(override val name: String) : - Character, Magician, Flyer { - override val type = "Dragon" - override fun skills() = - super.skills() + ", " + - super.skills() -} - -class Wizard(override val name: String) : - Character, Magician { - override val type = "Wizard" - override fun skills() = super.skills() -} - -class Goblin(override val name: String) : - Character, Fighter { - override val type = "Goblin" - override fun skills() = super.skills() -} - -fun match(c1: Character, c2: Character) { - c1.play() - trace("->") - c2.play() - trace(".") -} - -fun main() { - val characters: List = listOf( - Elf("Titania"), - FightingElf("Legolas"), - Warrior("Conan"), - Dragon("Puff"), - Wizard("Max"), - Goblin("Gorbag") - ) - characters.forEach { c1 -> - characters.filter { it != c1 } - .forEach { c2 -> match(c1, c2) } - } - trace eq """ - Titania Elf: Magic, Flying -> - Legolas FightingElf: - Magic, Flying, Fighting . - Titania Elf: Magic, Flying -> - Conan Warrior: Fighting . - Titania Elf: Magic, Flying -> - Puff Dragon: Magic, Flying . - Titania Elf: Magic, Flying -> - Max Wizard: Magic . - Titania Elf: Magic, Flying -> - Gorbag Goblin: Fighting . - Legolas FightingElf: - Magic, Flying, Fighting -> - Titania Elf: Magic, Flying . - Legolas FightingElf: - Magic, Flying, Fighting -> - Conan Warrior: Fighting . - Legolas FightingElf: - Magic, Flying, Fighting -> - Puff Dragon: Magic, Flying . - Legolas FightingElf: - Magic, Flying, Fighting -> - Max Wizard: Magic . - Legolas FightingElf: - Magic, Flying, Fighting -> - Gorbag Goblin: Fighting . - Conan Warrior: Fighting -> - Titania Elf: Magic, Flying . - Conan Warrior: Fighting -> - Legolas FightingElf: - Magic, Flying, Fighting . - Conan Warrior: Fighting -> - Puff Dragon: Magic, Flying . - Conan Warrior: Fighting -> - Max Wizard: Magic . - Conan Warrior: Fighting -> - Gorbag Goblin: Fighting . - Puff Dragon: Magic, Flying -> - Titania Elf: Magic, Flying . - Puff Dragon: Magic, Flying -> - Legolas FightingElf: - Magic, Flying, Fighting . - Puff Dragon: Magic, Flying -> - Conan Warrior: Fighting . - Puff Dragon: Magic, Flying -> - Max Wizard: Magic . - Puff Dragon: Magic, Flying -> - Gorbag Goblin: Fighting . - Max Wizard: Magic -> - Titania Elf: Magic, Flying . - Max Wizard: Magic -> - Legolas FightingElf: - Magic, Flying, Fighting . - Max Wizard: Magic -> - Conan Warrior: Fighting . - Max Wizard: Magic -> - Puff Dragon: Magic, Flying . - Max Wizard: Magic -> - Gorbag Goblin: Fighting . - Gorbag Goblin: Fighting -> - Titania Elf: Magic, Flying . - Gorbag Goblin: Fighting -> - Legolas FightingElf: - Magic, Flying, Fighting . - Gorbag Goblin: Fighting -> - Conan Warrior: Fighting . - Gorbag Goblin: Fighting -> - Puff Dragon: Magic, Flying . - Gorbag Goblin: Fighting -> - Max Wizard: Magic . - """ -} -``` \ No newline at end of file +"Max" and a `Goblin` named "Gorbag." \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 3/task.md b/Object-Oriented Programming/Polymorphism/Exercise 3/task.md index 069de5a8..b8a34c53 100644 --- a/Object-Oriented Programming/Polymorphism/Exercise 3/task.md +++ b/Object-Oriented Programming/Polymorphism/Exercise 3/task.md @@ -9,42 +9,4 @@ From `Base`, inherit a class called `Derived`. Override `f1()`, first tracing the same way. In `main()`, create a `Derived` object and upcast it to a `Base` reference. -Call `f1()` for this reference and explain the resulting trace. - -```kotlin -// Polymorphism/PolyExercise3.kt -package polymorphism -import atomictest.* - -private val trace = Trace() - -open class Base { - open fun f1() { - trace("Base.f1") - f2() - } - open fun f2() = trace("Base.f2") -} - -class Derived : Base() { - override fun f1() { - trace("Derived.f1") - super.f1() - } - override fun f2() { - trace("Derived.f2") - super.f2() - } -} - -fun main() { - val base: Base = Derived() - base.f1() - trace eq """ - Derived.f1 - Base.f1 - Derived.f2 - Base.f2 - """ -} -``` \ No newline at end of file +Call `f1()` for this reference and explain the resulting trace. \ No newline at end of file diff --git a/Object-Oriented Programming/Sealed Classes/Exercise 1/task.md b/Object-Oriented Programming/Sealed Classes/Exercise 1/task.md index 2bc5254c..a06922fa 100644 --- a/Object-Oriented Programming/Sealed Classes/Exercise 1/task.md +++ b/Object-Oriented Programming/Sealed Classes/Exercise 1/task.md @@ -5,69 +5,4 @@ the `Transport` class and add `trace("size ${transport.capacity}")` after the `when` expression in `travel()`. Then add new subclasses called `Tram` containing a `val route: String` and `Plane` containing a `val flightNumber: String`. Modify `travel()` to accomodate these new subclasses. Add `Tram` and -`Plane` to the `List` in `main()`. - -```kotlin -// SealedClasses/SealedEx1.kt -package sealedclassesex1 -import atomictest.* - -private val trace = Trace() - -sealed class Transport { - abstract val capacity: Int -} - -data class Train( - val line: String, - override val capacity: Int -) : Transport() - -data class Bus( - val number: String, - override val capacity: Int -) : Transport() - -data class Tram( - val route: String, - override val capacity: Int -) : Transport() - -data class Plane( - val flightNumber: String, - override val capacity: Int -) : Transport() - -fun travel(transport: Transport) { - when (transport) { - is Train -> - trace("Train ${transport.line}") - is Bus -> - trace("Bus ${transport.number}") - is Tram -> - trace("Tram ${transport.route}") - is Plane -> - trace("Plane ${transport.flightNumber}") - } - trace("size ${transport.capacity}") -} - -fun main() { - listOf( - Train("S1", 200), - Bus("11", 45), - Tram("22A Express", 60), - Plane("1103", 190) - ).forEach(::travel) - trace eq """ - Train S1 - size 200 - Bus 11 - size 45 - Tram 22A Express - size 60 - Plane 1103 - size 190 - """ -} -``` \ No newline at end of file +`Plane` to the `List` in `main()`. \ No newline at end of file diff --git a/Object-Oriented Programming/Sealed Classes/Exercise 2/task.md b/Object-Oriented Programming/Sealed Classes/Exercise 2/task.md index ac5e42cb..2b89970e 100644 --- a/Object-Oriented Programming/Sealed Classes/Exercise 2/task.md +++ b/Object-Oriented Programming/Sealed Classes/Exercise 2/task.md @@ -1,24 +1,4 @@ ## Sealed Classes (#2) Use `sealedSubclasses` to iterate through the classes in the previous -exercise. For each class, `trace()` its `simpleName`. - -```kotlin -// SealedClasses/SealedEx2.kt -package sealedclassesex1 -import atomictest.* - -private val trace = Trace() - -fun main() { - Transport::class.sealedSubclasses - .map { it.simpleName } - .forEach { trace(it) } - trace eq """ - Train - Bus - Tram - Plane - """ -} -``` \ No newline at end of file +exercise. For each class, `trace()` its `simpleName`. \ No newline at end of file diff --git a/Object-Oriented Programming/Sealed Classes/Exercise 3/task.md b/Object-Oriented Programming/Sealed Classes/Exercise 3/task.md index cb2da5dd..bd1237a3 100644 --- a/Object-Oriented Programming/Sealed Classes/Exercise 3/task.md +++ b/Object-Oriented Programming/Sealed Classes/Exercise 3/task.md @@ -3,27 +3,4 @@ Modify `SealedSubclasses.kt` so that all the subclasses of `Top` are nested within `Top`. Create a seeded random-number generator by defining `val rand = Random(17)`. Use this generator to randomly select a subclass of `Top` and -display its `simpleName`. - -```kotlin -// SealedClasses/SealedEx3.kt -package sealedclassesex3 -import atomictest.eq -import kotlin.random.Random - -sealed class Top { - class Middle1 : Top() - class Middle2 : Top() - open class Middle3 : Top() - class Bottom3 : Middle3() -} - -fun main() { - Top::class.sealedSubclasses - .map { it.simpleName } eq - "[Middle1, Middle2, Middle3]" - val rand = Random(17) - Top::class.sealedSubclasses - .random(rand).simpleName eq "Middle3" -} -``` \ No newline at end of file +display its `simpleName`. \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 1/task.md b/Object-Oriented Programming/Upcasting/Exercise 1/task.md index 5597268d..0429a639 100644 --- a/Object-Oriented Programming/Upcasting/Exercise 1/task.md +++ b/Object-Oriented Programming/Upcasting/Exercise 1/task.md @@ -11,54 +11,4 @@ Show that the compiler won't allow you to call `jump()`. In `main()`, create an instance of `Mouse` and `KangarooRat`, and show that you can call `jump()` for the latter. Pass both objects into `upcast()`, and -use `trace` to verify the output. - -```kotlin -// Upcasting/UpcastExercise1.kt -package upcasting -import atomictest.* - -private val trace = Trace() - -interface Rodent { - fun eat() - fun speak() -} - -class Mouse: Rodent { - override fun eat() = - trace("Mouse.eat") - override fun speak() = - trace("Mouse.speak") -} - -class KangarooRat: Rodent { - override fun eat() = - trace("KangarooRat.eat") - override fun speak() = - trace("KangarooRat.speak") - fun jump() = - trace("KangarooRat.jump") -} - -fun upcast(rodent: Rodent) { - rodent.eat() - rodent.speak() - // rodent.jump() // Won't compile -} - -fun main() { - val mouse = Mouse() - val kangarooRat = KangarooRat() - kangarooRat.jump() - upcast(mouse) - upcast(kangarooRat) - trace eq """ - KangarooRat.jump - Mouse.eat - Mouse.speak - KangarooRat.eat - KangarooRat.speak - """ -} -``` \ No newline at end of file +use `trace` to verify the output. \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 2/task.md b/Object-Oriented Programming/Upcasting/Exercise 2/task.md index 17ba52bb..93c007b3 100644 --- a/Object-Oriented Programming/Upcasting/Exercise 2/task.md +++ b/Object-Oriented Programming/Upcasting/Exercise 2/task.md @@ -16,61 +16,4 @@ From `Apple`, inherit `GrannySmith`, `Gala`, `Fuji` and `Braeburn`. Override `bite Gala`, `press Fuji` and `peel Braeburn`. In `main()`, make a `List` and populate it with the specific types of -`Apple`. Iterate through the list calling `consume()` for each object. - -```kotlin -// Upcasting/UpcastExercise2.kt -package upcasting -import atomictest.* - -private val trace = Trace() -private var counter = 0 - -abstract class Apple(val type: String) { - private val id = counter++ - init { - trace("$type $id") - } - abstract fun consume() -} - -class GrannySmith : Apple("GrannySmith") { - override fun consume() = - trace("chomp $type") -} - -class Gala : Apple("Gala") { - override fun consume() = - trace("bite $type") -} - -class Fuji : Apple("Fuji") { - override fun consume() = - trace("press $type") -} - -class Braeburn : Apple("Braeburn") { - override fun consume() = - trace("peel $type") -} - -fun main() { - val apples: List = listOf( - GrannySmith(), - Gala(), - Fuji(), - Braeburn() - ) - apples.forEach { it.consume() } - trace eq """ - GrannySmith 0 - Gala 1 - Fuji 2 - Braeburn 3 - chomp GrannySmith - bite Gala - press Fuji - peel Braeburn - """ -} -``` \ No newline at end of file +`Apple`. Iterate through the list calling `consume()` for each object. \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 3/task.md b/Object-Oriented Programming/Upcasting/Exercise 3/task.md index d7af986d..4ec65717 100644 --- a/Object-Oriented Programming/Upcasting/Exercise 3/task.md +++ b/Object-Oriented Programming/Upcasting/Exercise 3/task.md @@ -19,55 +19,4 @@ so that each function calls the member function avalable to its parameter. In `main()`, make a `Hero` object and pass it to each of the functions `t()`, `u()`, `v()`, and `w()` and validate the output using `trace`. Notice how passing a `Hero` to each of the functions upcasts it so that, inside the -function, the `Hero` becomes only the type of that parameter. - - -```kotlin -// Upcasting/UpcastExercise3.kt -package upcasting -import atomictest.* - -private val trace = Trace() - -interface Fight { - fun fight() -} - -interface Swim { - fun swim() -} - -interface Fly { - fun fly() -} - -open class ActionCharacter { - fun fight() = - trace("ActionCharacter fight") -} - -class Hero : - ActionCharacter(), Fight, Swim, Fly { - override fun swim() = trace("Hero swim") - override fun fly() = trace("Hero fly") -} - -fun t(x: Fight) = x.fight() -fun u(x: Swim) = x.swim() -fun v(x: Fly) = x.fly() -fun w(x: ActionCharacter) = x.fight() - -fun main() { - val h = Hero() - t(h) // Treat it as a Fight - u(h) // Treat it as a Swim - v(h) // Treat it as a Fly - w(h) // Treat it as an ActionCharacter - trace eq """ - ActionCharacter fight - Hero swim - Hero fly - ActionCharacter fight - """ -} -``` \ No newline at end of file +function, the `Hero` becomes only the type of that parameter. \ No newline at end of file