hfhbd
01/26/2022, 3:05 PMUnit
or Nothing
.
Usecase: A generic Converter
interface:
interface Converter<Input: Any, Output: Any> {
fun convert(input: Input?): Output?
}
// normal (old) usage
class StringToIntConverter: Converter<String, Int> {
override fun convert(input: String?) = input?.toIntOrNull()
}
But sometime, you need to adopt the usage, because you always return a value unrelated to its inputs or simple log and fail:
class FixedIntConverter(val unrelatedReturnValue: Int): Converter<Nothing, Int> {
override fun convert(input: Nothing?) = unrelatedReturnValue
}
class IgnoreConverter: Converter<Int, Nothing> {
override fun convert(input: Int?) = error("$input")
}
To understand, which Nothing
matches to which generic type, you have to read the interface declaration. With named generics, you don't have to look up the declaration, because it is understandable by its name. This is also very useful, when you can't simple go to the declaration without any tools, eg in the GitHub PR diff view..
class FixedIntConverter(val unrelatedReturnValue: Int): Converter<Input=Nothing, Int> {
override fun convert(input: Nothing?) = unrelatedReturnValue
}
class IgnoreConverter: Converter<Int, Output=Nothing> {
override fun convert(input: Int?) = error("$input")
}
Like named arguments, the same rules and behavior should apply, so naming is optional.ilya.gorbunov
01/26/2022, 3:33 PMhfhbd
01/26/2022, 3:36 PMAllowing to specify type argument names at a type instantiation site would make their names a part of the type contract too, and that may be unexpected for those who get used to the opposite.
Isn't the same true about named function parameters, is it? Changing fun foo(a: String)
to a fun foo(b: String)
results into a compile error when consuming too.hfhbd
01/26/2022, 3:43 PM