https://kotlinlang.org logo
Title
p

Phani Mahesh

05/17/2022, 7:43 AM
not sure if there is a better channel but what is the advantage of definitely non nullable types?
j

Joffrey

05/17/2022, 7:52 AM
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

Roukanken

05/17/2022, 7:54 AM
I think in cases like these it's needed iirc?
class Collection<T> {
    fun getOrElse(key: Int, default: T & Any): T & Any
}
p

Phani Mahesh

05/17/2022, 7:57 AM
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

Tobias Suchalla

05/17/2022, 8:17 AM
Example: You want to write your own elvis-operator-like function, then you cannot restrict your type:
fun <T> getOrDefault(nullable: T, default: T & Any): T & Any
Edit: You just used the same example in the channel, mea culpa...
v

Vampire

05/17/2022, 8:36 AM
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?
r

Ruckus

05/17/2022, 4:40 PM
@Tobias Suchalla What advantage does that provide over:
fun <T: Any> getOrDefault(nullable: T?, default: T): T
v

Vampire

05/17/2022, 4:53 PM
That's exactly the question
r

Ruckus

05/17/2022, 5:04 PM
@Vampire Ah, it seems I missed some context between the time you wrote your comment and @Tobias Suchalla edited theirs. My bad 🙂
v

Vampire

05/17/2022, 7:15 PM
No, my answer was after his edit. 😛
r

Ruckus

05/17/2022, 7:19 PM
In that case, I am clearly just confused
t

Tobias Suchalla

05/18/2022, 5:39 AM
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

Dan Fingal-Surma

05/18/2022, 9:08 AM
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

Joffrey

05/18/2022, 3:03 PM
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

Dan Fingal-Surma

05/18/2022, 3:38 PM
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

Joffrey

05/18/2022, 3:42 PM
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

Roukanken

05/18/2022, 3:42 PM
Exactly
j

Joffrey

05/18/2022, 3:44 PM
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

Dan Fingal-Surma

05/18/2022, 3:45 PM
This is exactly the form of the Java class I realized couldn't move to Kotlin yet last week 😃
j

Joffrey

05/18/2022, 3:49 PM
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