Just wanted to share to whoever might be able to a...
# getting-started
r
Just wanted to share to whoever might be able to address it that it's frustrating to work with multi-module apps in Kotlin. Smart casting won't work since it's not safe, which is understandable. The problem is that the whole purpose of using Kotlin is to work with cleaner code than Java, now:
Copy code
if (myObj.getDate() == null || myObj.getDate().isBefore(...)) // java
looks in fact cleaner than
Copy code
if (myObj.date == null || myObj.date!!.isBefore(...)) // Kotlin
since Kotlin insists that the module can change and thus can't guarantee non-nullability. This would be fine for libraries, but the module where myObj is defined is part of my app and compiled together, it's just a matter of internal organization. Is there a way to enable a less strict smart casting?
y
I think there's the concept of "friend modules". Perhaps a compiler option?
e
no, friends are something else (different source sets in the same module, allowing
internal
visibility)
w
If you like the imperative smart casted style, I don't know of anything to make Kotlin more lenient. One of the powerful things of properties is that they abstract their underlying implementation, but this indeed means that
myObj.getDate() == null || myObj.getDate().isBefore(...)
is technically not safe given that you can not assume it's implementation (KT-50534 linked above is a proposal to allow the compiler to be able to assume some implementations). Another thing that could solve this are value types. (but most likely will take a long time (but idk, I'm not involved in the compiler or design team)) The nice thing about value semantics is that they are not only easier for you to comprehend, but also for the compiler, allowing improved analysis like you're suggesting. Since Kotlin can not offer something for imperative/Java style approach, here's some alternatives: • If you are slowly getting used to Kotlin's more functional approach, you might like be able to live with:
myObj.date.let { it != null || it.isBefore(...) }
. • You could even make your own wrapper if you feel like making it read more natural:
myObj.data.isNullOr { it.isBefore(...) }
. • Alternatively (I personally would really not recommend this, it contains nullable booleans which are significantly harder to comprehend!), you could do:
myObj.data?.isBefore(...) != false
.
plus1 1
c
You can also just write:
Copy code
val date = myObj.date
if (date == null || date.isBefore(…))
smart-casting will work there, since the value can't change (it's a local variable)
2
h
You can use the friendPath/friendModule compiler/task option to access internal code, but IntelliJ isn’t able to get the task option so it shows an error. We did use this workaround in the past but without IntelliJ supports it’s annoying so we switched back to variables or !!.
r
Thanks for all the replies, folks. I'll take a look at what works best (probably local variables). It's a shame that Kotlin doesn't support this though, would be really nice to see that YouTrack request be implemented