not sure if there is a better channel but what is ...
# getting-started
p
not sure if there is a better channel but what is the advantage of definitely non nullable types?
j
It was necessary in some cases of implementing some java interfaces as far as I remember, but most of the time in pure Kotlin it's redundant
r
I think in cases like these it's needed iirc?
Copy code
class Collection<T> {
    fun getOrElse(key: Int, default: T & Any): T & Any
}
p
Ah. makes sense. but I can’t think of practical applications where I would prefer this over using a bound on the type param itself
t
Example: You want to write your own elvis-operator-like function, then you cannot restrict your type:
Copy code
fun <T> getOrDefault(nullable: T, default: T & Any): T & Any
Edit: You just used the same example in the channel, mea culpa...
v
How is the other version restricted?
x
is still nullable, isn't it? Where is the difference between the two examples of OP besides the second one being more readable and looking more idiomatic?
That's exactly the question
No, my answer was after his edit. 😛
t
I just reiterated what I thought to have read somewhere.. 😄 But the KEEP and anouncement mention Java interop as the main driver behind this solution as Java does not support explicit nullability. In a pure Kotlin environment it does indeed seem to be unnecessary^^
d
Imagine you have two classes: Foo<T> and Bar<T : Any>. Now add Bar as a val of Foo without modifying Foo's type parameter.
The getOrElse posted above also qualifies, as you cannot correctly introduce a new type parameter there.
As a pure Kotlin example, Bar could be KClass.
j
The getOrElse posted above also qualifies, as you cannot correctly introduce a new type parameter there.
The
getOrElse
above is a member function, which means if you control it you also control the class itself. You could declare the class with
T : Any
and add
T?
everywhere instead of
T
, and use
T
instead of
T & Any
.
Now add Bar as a val of Foo without modifying Foo's type parameter.
You control
Foo
here, so you can change `Foo`'s parameter (and again, update all
T
to
T?
). Or do you mean it's about backwards compatibility? That could be a fair point.
d
It may not be correct to change the parameter. Let Foo be ColumnType<T>, where T represents the type you can get out of an object (eg fun <T> get(c: ColumnType<T>). And you need the KClass inside ColunnType.
Changing <T> to <T : Any> and adding T? places does not in general retain the same semantics, as you have introduced definitely nullable types where they were not before.
👍 1
j
Ah I see what you mean. You want the user to be able to distinguish
ColumnType<String>
from
ColumnType<String?>
, and yet be able to represent the non-nullable
KClass<String>
in both cases. That makes sense, thanks!
r
Exactly
j
Changing <T> to <T : Any> and adding T? places does not in general retain the same semantics, as you have introduced definitely nullable types where they were not before.
Indeed, for some reason I missed this.
d
This is exactly the form of the Java class I realized couldn't move to Kotlin yet last week 😃
j
Haha I feel you. Still, I think the example in the release notes is poorly chosen, as it doesn't really show the benefit of definitely-not-null types since that use case could be expressed before with
<T : Any>
(since the function itself is generic and only takes
T
as input, it is safe to introduce definitely nullable type): https://kotlinlang.slack.com/archives/C0B8MA7FA/p1652773490430979