Reworked exercises for 'Abstract Classes'
This commit is contained in:
parent
7ee015f993
commit
454887eee4
|
@ -1,29 +1,20 @@
|
|||
// Abstract/AbsExercise1.kt
|
||||
package abstractClassesExercise1
|
||||
import atomictest.*
|
||||
|
||||
private val trace = Trace()
|
||||
import atomictest.eq
|
||||
|
||||
abstract class WithParams(
|
||||
val i: Int,
|
||||
var s: String = ""
|
||||
) {
|
||||
init {
|
||||
trace("WithParams $i $s")
|
||||
}
|
||||
interface Movable {
|
||||
fun move() = "move"
|
||||
}
|
||||
|
||||
class Concrete(i: Int, s: String):
|
||||
WithParams(i, s) {
|
||||
init {
|
||||
trace("Concrete $i $s")
|
||||
}
|
||||
interface Sleepable {
|
||||
fun sleepOn() = "sleep"
|
||||
}
|
||||
|
||||
class Sofa: Movable, Sleepable
|
||||
|
||||
fun main() {
|
||||
Concrete(11, "One Louder")
|
||||
trace eq """
|
||||
WithParams 11 One Louder
|
||||
Concrete 11 One Louder
|
||||
"""
|
||||
val sofa = Sofa()
|
||||
sofa.move() eq "move"
|
||||
sofa.sleepOn() eq "sleep"
|
||||
}
|
|
@ -2,5 +2,23 @@ type: edu
|
|||
files:
|
||||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 84
|
||||
length: 17
|
||||
placeholder_text: abstract class Movable
|
||||
- offset: 129
|
||||
length: 19
|
||||
placeholder_text: abstract class Sleepable
|
||||
- offset: 180
|
||||
length: 30
|
||||
placeholder_text: '// class Sofa: Movable(), Sleepable()'
|
||||
- offset: 225
|
||||
length: 71
|
||||
placeholder_text: |-
|
||||
/*
|
||||
val sofa = Sofa()
|
||||
sofa.move() eq "move"
|
||||
sofa.sleepOn() eq "sleep"
|
||||
*/
|
||||
- name: test/Tests.kt
|
||||
visible: false
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
## Abstract Classes (#1)
|
||||
|
||||
Abstract classes can have parameters and constructors just like ordinary
|
||||
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.
|
||||
The starter code tries to use multiple inheritance with abstract classes:
|
||||
it defines `Movable` and `Sleepable` abstract classes and tries to define
|
||||
the class `Sofa` which inherits both.
|
||||
|
||||
Convert `Movable` and `Sleepable` to interfaces to make the code compile.
|
|
@ -1,34 +1,19 @@
|
|||
// Abstract/AbsExercise2.kt
|
||||
package abstractClassesExercise2
|
||||
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 Instrument(val name: String, val action: String) {
|
||||
fun play(n: Note): String = "$name $action $n"
|
||||
}
|
||||
|
||||
open class Wind : Instrument("Wind") {
|
||||
override fun play(n: Note) {
|
||||
trace("$name blow $n")
|
||||
}
|
||||
}
|
||||
class Wind : Instrument("Wind", "blow")
|
||||
|
||||
class Percussion : Instrument("Percussion") {
|
||||
override fun play(n: Note) {
|
||||
trace("$name strike $n")
|
||||
}
|
||||
}
|
||||
class Percussion : Instrument("Percussion", "strike")
|
||||
|
||||
class Stringed : Instrument("Stringed") {
|
||||
override fun play(n: Note) {
|
||||
trace("$name pluck $n")
|
||||
}
|
||||
}
|
||||
class Stringed : Instrument("Stringed", "pluck")
|
||||
|
||||
fun tune(i: Instrument) = i.play(Note.C)
|
||||
|
||||
|
@ -38,10 +23,12 @@ fun main() {
|
|||
Percussion(),
|
||||
Stringed()
|
||||
)
|
||||
orchestra.forEach { tune(it) }
|
||||
trace eq """
|
||||
Wind blow C
|
||||
Percussion strike C
|
||||
Stringed pluck C
|
||||
"""
|
||||
}
|
||||
for (instrument in orchestra) {
|
||||
println(tune(instrument))
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
Wind blow C
|
||||
Percussion strike C
|
||||
Stringed pluck C
|
||||
*/
|
|
@ -2,5 +2,30 @@ type: edu
|
|||
files:
|
||||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 105
|
||||
length: 112
|
||||
placeholder_text: |-
|
||||
abstract class Instrument {
|
||||
abstract fun play(n: Note): String
|
||||
}
|
||||
- offset: 219
|
||||
length: 39
|
||||
placeholder_text: |-
|
||||
class Wind : Instrument() {
|
||||
override fun play(n: Note) = "Wind blow $n"
|
||||
}
|
||||
- offset: 260
|
||||
length: 53
|
||||
placeholder_text: |-
|
||||
class Percussion : Instrument() {
|
||||
override fun play(n: Note) = "Percussion strike $n"
|
||||
}
|
||||
- offset: 315
|
||||
length: 48
|
||||
placeholder_text: |-
|
||||
class Stringed : Instrument() {
|
||||
override fun play(n: Note) = "Stringed pluck $n"
|
||||
}
|
||||
- name: test/Tests.kt
|
||||
visible: false
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
## Abstract Classes (#2)
|
||||
|
||||
Make an `enum` called `Note` with values `A`-`G`. Create an `abstract` class
|
||||
`Instrument` that takes a `val` class argument `name: String` which holds the
|
||||
name of the class. Add an `abstract` member function `play(n: Note)`.
|
||||
The starter code contains an `abstract` class `Instrument` that contains
|
||||
an `abstract` member function `play(n: Note)`. `Note` is defined as an enum
|
||||
with values `A`-`G`.
|
||||
|
||||
Now inherit `Wind`, `Percussion` and `Stringed` from `Instrument`, overriding
|
||||
`play()` in each case to use `atomictest.Trace` to show the class name, then
|
||||
`blow` for `Wind`, `strike` for `Percussion`, and `pluck` for `Stringed`, and
|
||||
finally the `Note` being played.
|
||||
The classes `Wind`, `Percussion` and `Stringed` all inherit `Instrument`,
|
||||
overriding `play()` in each case to return the string containing the class name,
|
||||
then `blow` for `Wind`, `strike` for `Percussion`, and `pluck` for `Stringed`,
|
||||
and finally the `Note` being played.
|
||||
|
||||
Add a function `tune()` that takes an `Instrument` parameter and plays that
|
||||
`Instrument` using `Note.C`.
|
||||
|
||||
In `main()`, create an `orchestra` which is a `List<Instrument>` containing an
|
||||
instance of each type of `Instrument`. Call `tune()` for each `Instrument` in
|
||||
the `orchestra`, and validate the results using `Trace`.
|
||||
Add two constructor arguments to the class `Instrument`: `name` and `action`,
|
||||
and pass the corresponding values in the subclasses. Make `name` and `action`
|
||||
`val` properties and provide an implementation of the `play` function in the
|
||||
superclass so that it returned the same value as before for each subclass.
|
||||
Remove implementations of `play` from the subclasses.
|
|
@ -1,65 +0,0 @@
|
|||
// Abstract/AbsExercise3.kt
|
||||
package abstractClassesExercise3
|
||||
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
|
||||
"""
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
type: edu
|
||||
files:
|
||||
- name: src/Task.kt
|
||||
visible: true
|
||||
- name: test/Tests.kt
|
||||
visible: false
|
|
@ -1,2 +0,0 @@
|
|||
id: 1305732
|
||||
update_date: Tue, 12 May 2020 16:23:49 UTC
|
|
@ -1,7 +0,0 @@
|
|||
## Abstract Classes (#3)
|
||||
|
||||
Add classes to the previous example: `Bowed` inherits from `Stringed` and uses
|
||||
`bow` instead of `plucked` in the output, while `Brass` and `Reed` are `Wind`
|
||||
subclasses. `Brass` and `Reed` do not override `play()`. Make the necessary
|
||||
modifications to allow each class to accept a `String` argument containing the
|
||||
class name.
|
|
@ -1,11 +0,0 @@
|
|||
package abstractClassesExercise3
|
||||
|
||||
import org.junit.Test
|
||||
import util.unimplementedTest
|
||||
|
||||
class TestAbstractClassesExercise3 {
|
||||
@Test fun testSolution() {
|
||||
//TODO: implement your test here
|
||||
unimplementedTest()
|
||||
}
|
||||
}
|
|
@ -2,4 +2,3 @@ content:
|
|||
- Examples
|
||||
- Exercise 1
|
||||
- Exercise 2
|
||||
- Exercise 3
|
||||
|
|
Loading…
Reference in New Issue