Reputation: 624
I have an extension function something like this:
inline fun <A, B, C> Pair<A, B>.notNull(code: (A, B) -> C) {
if (this.first != null && this.second != null) {
code(this.first, this.second)
}
}
with that, I can do something like this:
Pair(username, password).notNull { user, pass ->
// code to execute when username and password is not null
}
The problem is, user and password type is still in nullable form, so I still need to use ?.
to call user and pass, even though user and pass is not null
How to cast it to their respective not nullable type?
Maybe something like this, but for generic:
inline fun <C> Pair<Editable?, Editable?>.notNull(code: (Editable, Editable) -> C) {
if (this.first != null && this.second != null) {
code(this.first!!, this.second!!)
}
}
Upvotes: 0
Views: 403
Reputation: 15552
I think this will work.
inline fun <A: Any, B: Any, C> Pair<A?, B?>.notNull(code: (A, B) -> C) {
if (this.first != null && this.second != null) {
code(this.first!!, this.second!!)
}
}
Here, the types A
and B
are not defined to be subtypes of Any?
. They are restricted to subtypes of Any
, so they are not null. (Of course, every subtype of Any
is a subtype of Any?
.)
However, the type of this
will be Pair<A?, B?>
, so it will be a pair of nullables. All not-null types are subtypes of their corresponding nullable types, so any Pair can call this extension function.
!!
): https://stackoverflow.com/a/48960855/869330
Upvotes: 1
Reputation: 97133
In this case the smart cast does not work because you're accessing properties of a class declared in another module. It will work if you store the property values in local variables:
inline fun <A : Any, B : Any, C> Pair<A?, B?>.notNull(code: (A, B) -> C) {
val first = this.first
val second = this.second
if (first != null && second != null) {
code(first, second)
}
}
Upvotes: 2
Reputation: 2643
General Answer :
if you declare a generic class or function they can include nullable while substituting their type params :
Example :
class Help<T>{
fun printHelp(message :T){
message?.render();
}
}
so in this case message is nullable despite T isn't marked with T? So to avoid passing a nullable parameter type and guarantee that a non-null type will always be substituted you can change it to :
class Help<T : Any>{
fun printHelp(message :T){
message.render();
}
}
Upvotes: 2