Liudvikas Sablauskas
01/05/2022, 1:10 PM/**
* Task: Make line `DisNonNullable.nonNull()` not compile
* Clarification: `DisNonNullable.nonNull()` will always have a non-null value, so it makes sense to not allow that method
* Clarification: Everything else has to compile just as before, only `DisNonNullable.nonNull()` should fail
* Clarification: The non-generic parameter type String is chosen only as an example. This hardcoded type is not the focus of the task
* Restrictions: Mustn't modify main() method, DisNullable and DisNotNullable classes
*/
fun main(args: Array<String>) {
DisNullable.nonNull()
DisNonNullable.nonNull()
}
abstract class GenericMapper<T> {
abstract fun map(string: String): T
fun nonNull(): GenericMapper<T> {
val delegate = this
return object : GenericMapper<T>() {
override fun map(string: String): T {
return delegate.map(string)
}
}
}
}
object DisNullable : GenericMapper<String?>() {
override fun map(string: String) = string
}
object DisNonNullable : GenericMapper<String>() {
override fun map(string: String) = string
}
Rob Elliot
01/05/2022, 1:23 PMfun main(args: Array<String>) {
DisNullable.nonNull()
DisNonNullable.nonNull()
}
// Internal so that there are only two immediate subtypes, but it isn't sealed, so other subtypes of
// those immediate subtypes can be defined in other packages.
abstract class GenericMapper<T> internal constructor() {
abstract fun map(string: String): T
}
abstract class NullableGenericMapper<T> : GenericMapper<T>() {
fun nonNull(): GenericMapper<T> {
val delegate = this
return object : GenericMapper<T>() {
override fun map(string: String): T {
return delegate.map(string)
}
}
}
}
abstract class NonNullableGenericMapper<T : Any> : GenericMapper<T>()
object DisNullable : NullableGenericMapper<String?>() {
override fun map(string: String) = string
}
object DisNonNullable : NonNullableGenericMapper<String>() {
override fun map(string: String) = string
}
fun nonNull()
when I wrote that. Guess in my version it should return NonNullableGenericMapper
.Liudvikas Sablauskas
01/05/2022, 1:39 PMRob Elliot
01/05/2022, 1:41 PMLiudvikas Sablauskas
01/05/2022, 1:42 PMobject DisNullable : GenericMapper<String?>() {
override fun map(string: String) = string
}
object DisNonNullable : GenericMapper<String>() {
override fun map(string: String) = string
}
This should not change at allRob Elliot
01/05/2022, 1:42 PMLiudvikas Sablauskas
01/05/2022, 1:43 PMRob Elliot
01/05/2022, 1:44 PMLiudvikas Sablauskas
01/05/2022, 1:46 PM"The constraints are arbitrary and it may be impossible to meet themNo, I just said that
But I definitely remember that there was a solution, exactly according to these rules
Rob Elliot
01/05/2022, 1:47 PMabstract class NullableGenericMapper<E : Any> : GenericMapper<E?>() {
fun nonNull(): NonNullableGenericMapper<E> = TODO()
}
object DisNullable : NullableGenericMapper<String>() {
override fun map(string: String): String? = null
}
Jason5lee
01/05/2022, 2:34 PMClarification: `DisNonNullable.nonNull()` will always have a non-null value, so it makes sense to not allow that method
It does not make sense to me.Rob Elliot
01/05/2022, 2:46 PMnonNull
is to transform a GenericMapper<String?>
into a GenericMapper<String>
so that when you call map
on it you get back a String
not a String?
.
So calling GenericMapper<String>.nonNull()
is pointless - it would effectively return itself - and the idea is to make it not compile so that people don't accidentally call it.Liudvikas Sablauskas
01/05/2022, 2:49 PMRob Elliot
01/05/2022, 3:07 PMfun main(args: Array<String>) {
DisNullable.nonNull()
DisNonNullable.nonNull()
}
abstract class GenericMapper<T> {
abstract fun map(string: String): T
}
fun <T> GenericMapper<T?>.nonNull(): GenericMapper<T> {
val delegate = this
return object : GenericMapper<T>() {
override fun map(string: String): T {
return delegate.map(string) ?: TODO("handle null")
}
}
}
object DisNullable : GenericMapper<String?>() {
override fun map(string: String) = string
}
object DisNonNullable : GenericMapper<String>() {
override fun map(string: String) = string
}
Liudvikas Sablauskas
01/05/2022, 3:25 PM