I have a generic type (T: Any?
) that I need constrained in one situation never to be null
:
class Repository<T> { // T may be a non-null or nullable type.
fun getFromFoo(): T {}
fun getFromBar(): T {} // This is never null. Can I mark it as so?
}
val repository = Repository<String>()
val fromFoo: String = repository.getFromFoo() // Returns a non-null String.
val fromBar: String = repository.getFromBar() // How do I make this work?
val repository = Repository<String?>()
val fromFoo: String? = repository.getFromFoo() // Returns a nullable String.
val fromBar: String = repository.getFromBar() // How do I make this return a non-null String?
While I would ideally refactor these into separate types (like FooRepository
and BarRepository
), is there any way to get this type constraint functionality?
A type constraint in general is an inequation of the following form: T <: U T <: U T <: U where T T T and U U U are concrete Kotlin types. As Kotlin has parameterized types, T T T and U U U may be free type variables: unknown types which may be substituted by any other type in Kotlin.
Not-Null Assertion Each type in Kotlin has one nullable form and another non-nullable form. For instance, the Int type can hold non-null 32-bit integers. In addition to the same values, the Int? type can hold null values, too. Kotlin provides many options to facilitate working with nullable data types in a safe manner.
Kotlin generics. Generics are the powerful features that allow us to define classes, methods and properties which are accessible using different data types while keeping a check of the compile-time type safety. A generic type is a class or method that is parameterized over types. We always use angle brackets () to specify the type parameter in ...
Any is the supertype of all non-null types in Kotlin. So, to make a generic class accept only non-null type arguments, you need to explicitly specify Any as an upper bound of T, that is T : Any. This results in the T being non-null in the following example:
What you need is the type T & Any
— an intersection of generic T
and Any
. It represents such subtype of T
that can never contain nulls.
Unfortunately the intersection types and this intersection in particular currently are non-denotable in Kotlin, meaning that you can't declare a return type of a function to be non-nullable subtype of T
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With