Тема: Kotlin. Generics
Добрий вечір. Допоможіть, будь ласка. Перше завдання було неважке, тому друге напевно також має бути легке, але я не можу його зробити. Entities.kt і ResultPrinter.kt допоміжні файли для Task2Transformer.kt.
Опис завдань є в коді, в коментарях.
Як я зрозумів: Transformer - це екземпляр операції. Всі операції зв'язані так як і в LinkedList, тобто посиланням на наступний об'єкт іншого типу - next, а також операція яка приведе до цього типу - action, і сама операція - onNext.
Файл Entities.kt
/**
* Some data classes for running examples of Transformer Task
*/
data class State(
val data: Data? = null,
val error: Error? = null
)
data class Error(
val code: Int = 0,
val message: String? = null
)
data class Data(val value: Number)
Файл ResultPrinter.kt
/**
* Class which prints results of optional values
* If value exists (non-null) it prints: "No value"
* Otherwise calls standard toString method
*/
open class ResultPrinter<T : Any>(private val value: Optional<T>) {
open fun print() {
if (value.exists) {
println(value.get())
} else {
println("No value")
}
}
}
Файл Task1Optional.kt
/**
* TODO Write generic class Optional which allows
* - to check whether [value] which it was created with [exists] or null
* - retrieve value if it is not null [get]
* - in case value is null get should cause NullPointerException
* - retrieve nullable version of value [getOrNull]
*
* There should be a companion object extension method [toOptional] which allows
* to create Optional object from `Any?` object
*/
class Optional <T> private constructor(
private val value: T?
) {
val exists: Boolean = value != null
fun get() = if (exists) value else throw NullPointerException()
fun getOrNull() = if (exists) value else null
companion object {
fun <T> T.toOptional(): Optional<T> = Optional(this)
}
}
Файл Task2Transformer.kt
import com.company.generics.Optional.Companion.toOptional
/**
* TODO Finish Transformer class
* This class allows to chain several conversion operations.
* Whenever new value is sent to provided [source] the whole chain should made appropriate conversions
* and return expected result in lambda provided to [transform] method.
*
* Transformer class does not support nullable values (same as Observable in RxJava).
* Otherwise NullPointerException will be thrown during conversions.
*
* For convenience [Optional] type is used and results are printed using [ResultPrinter]
*
* Please check [main] method for the reference how it should work
*/
class Transformer<T>(private val source: Source<T>) {
init {
source.subscribe(this)
}
private var onNext: /*TODO Add type*/ = null
private var next: Transformer<Any>? = null
private var action: (Any) -> T = { it as T }
fun transform(onNext: /*TODO Add type*/) {
this.onNext = onNext
}
fun map(/*TODO Add generic argument*/): Transformer</*Another type than T*/> {
return TODO("Write implementation")
}
private fun next(value: T) {
val next = next
if (next == null) {
onNext?.invoke(action(value!!))
} else {
next.source.send(action(value!!)!!)
}
}
class Source<S> {
private var listener: Transformer<S>? = null
fun subscribe(transformer: Transformer<S>) {
this.listener = transformer
}
fun send(value: S) {
listener?.next(value)
}
}
}
/**
* Code below is a specification and should compile and work as described
*/
fun main() {
val source = Transformer.Source<State>()
Transformer(source)
.map { it.data.toOptional() }
.transform {
ResultPrinter(it).print()
}
source.send(State()) // -> "No value"
source.send(State(data = Data(1))) // -> "Data(value=1)"
val errorSource = Transformer.Source<Error>()
Transformer(errorSource)
.map { it.message.toOptional() }
.transform {
ResultPrinter(it).print()
}
errorSource.send(Error()) // -> "No value"
errorSource.send(Error(message = "Generics are awesome")) // -> "Generics are awesome"
Transformer(source)
.map { (it.error?.message).toOptional() }
.transform {
ResultPrinter(it).print()
}
source.send(State()) // -> "No value"
source.send(State(error = Error(0, null))) // -> "No value"
source.send(State(
error = Error(0, "Generics are awesome")
)) // -> "Generics are awesome"
}
Дякую за витрачений час.