1
1
Fork 0

Reworked exercises for 'Abstract Classes'

This commit is contained in:
Svetlana Isakova 2020-05-14 19:52:56 +02:00
parent 7ee015f993
commit 454887eee4
12 changed files with 84 additions and 157 deletions

View File

@ -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"
}

View File

@ -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

View File

@ -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.

View File

@ -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
*/

View File

@ -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

View File

@ -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.

View File

@ -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
"""
}

View File

@ -1,6 +0,0 @@
type: edu
files:
- name: src/Task.kt
visible: true
- name: test/Tests.kt
visible: false

View File

@ -1,2 +0,0 @@
id: 1305732
update_date: Tue, 12 May 2020 16:23:49 UTC

View File

@ -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.

View File

@ -1,11 +0,0 @@
package abstractClassesExercise3
import org.junit.Test
import util.unimplementedTest
class TestAbstractClassesExercise3 {
@Test fun testSolution() {
//TODO: implement your test here
unimplementedTest()
}
}

View File

@ -2,4 +2,3 @@ content:
- Examples
- Exercise 1
- Exercise 2
- Exercise 3