I’m wondering. Kotlin doesn’t allow you to call me...
# announcements
k
I’m wondering. Kotlin doesn’t allow you to call methods with generics with specifying the type - which is one of the few situations where I’m forced to write more code than with Java. e.g.
val example = listOf()
won’t compile, I must write
val example = listOf<Any>()
see examples: https://kotlinlang.slack.com/archives/C0922A726/p1514989124000312?thread_ts=1514986352.000228&amp;cid=C0922A726 https://kotlinlang.slack.com/archives/C0922A726/p1514987282000262?thread_ts=1514986352.000228&amp;cid=C0922A726 Why is this forced? I’ve Googled but can’t find discussion on it
l
@kassim Please, edit your message to provide an example
k
@louiscad done 🙂
d
Because in
val list = listOf()
what type should the list have? It is not specified.
👆 3
And there is nothing there for the compiler to infer it.
2
k
without inference, why wouldn’t it be bound for
Any
?
d
Why wouldn't it be
String
or
Foo
or
Any?
? There is no reason for it to be any of these.
Hence you need to specify which you want.
l
Why not
Nothing
? or
Nothing?
? And what would happen when you would add something in the vararg? The type would magically change, breaking code?
k
^ yes
you can’t assume it’s
Nothing?
but
Any?
is something that can be assumed
d
Why?
k
because it accommodates
ok so my confusion is, why doesn’t it work as Java does? which is the behaviour I’m describing
I know what you guys think is right is right, but what benefit does it bring to not behave in the way that Java does in this case?
d
Java does not "just assume object".
k
no?
d
Please show what you are referring to in Java.
l
@kassim But as I said, it'd break code when you'd add something in the
listOf()
vararg. It works in Java because Java allows raw generics, but Kotlin doesn't, so you need to specify the generic type
And if the generic type can be inferred from a parameter, you can omit to specify it explicitly, but in your example, this is not the case
g
Even in Java code with raw generics smells and compiler emits warnings
1
d
Oh, raw types? You should never be using those! 😮
l
If you add
Any()
as argument of
listOf(...)
for example, the type will be able to be inferred though.
k
ok I was using listOf as an assumingly easy example, maybe it’s too easy to argue against ok so my actual use case is (Android code)
Copy code
protected <A extends BaseActivity> A getBaseActivity() {
return (A) getActivity();
}
I want to call this from my Kotlin code and call
Copy code
getBaseActivity().someMethodInBaseActivityClass()
but I have to write
Copy code
getBaseActivity<BaseActivity>().someMethodInBaseActivityClass()
I don’t care what the actual class is, the method is contained within the
BaseActivity
class - but I’m still having to specify that, in my opinion, unnecessarily
d
That is, unfortunately, due to the bad design of said method, constrained by it being written in Java.
It's abusing generics a bit 😄
k
hmm, I think “bad design” of the method is arguable, but lets not digress too much.. if we know a method will undoubtedly return a certain type (because the return type is a generic that extends class A), why should we have to specify it?
d
Because it's explicit. Kotlin by design tries to avoid "hidden magic".
k
but why would it be considered “hidden magic”?
d
Because it is just deciding on "some type to put there".
k
its not “some type” its “the type that will certainly be returned”
l
@kassim What Kotlin has is type inference. What you are looking for is default type for generics, which is not a thing in Kotlin at the moment
d
No. It could be any of the subtypes of
BaseActivity
that will be returned.
l
@diesieben07
BaseActivity
? I don't see such thing in this thread's context...
d
In @kassim's example
l
@diesieben07 Oh, I missed these messages
@kassim In your example, you have a generic function (it's not of the type of the class) with no parameter to infer its type, so you need to specify it. But maybe your function just shouldn't be generic?
k
yeah I’m aware its not available @louiscad - I’m just wondering “why not?” it seems to be something that’s discussed a bit (thanks for the refs @kirillrakhman) and they’re considering proposals for version 1.3
l
Probably because the design of your initial message of this thread that looked like raw generics aka code smell (the
listOf()
defaulting to
Any
[why not
Any?
or
Nothing
?]) would be made possible, which could introduce confusion and mistakes over the course of codebases lives.
k
in the case for my function, it doesn’t need to be generic for the given use, but does need to be for other uses - it doesn’t make sense to define it otherwise other than to not have to write it without the type parameter, which doesn’t really make sense to me
yeah I made a mistake of starting with the
listOf
example
so Google/Android has a similar method to mine
Copy code
public final <T extends View> T findViewById(@IdRes int id) {
        if (id == NO_ID) {
            return null;
        }
        return findViewTraversal(id);
    }
if a user just wanted to disable a view,
Copy code
findViewById(ID).enabled = false
but
Copy code
findViewById(ID)<View>.enabled = false
is necessary you can argue if you want that that’s “hidden magic” anyways, thanks for responding, I guess the actual answer is “it hasn’t been addressed yet”
l
So your point is to allow to omit generic specification when you're not using any generic part of the result. But what if you then change your mind and need to store the result in a
val
before, to do multiple operations (even if not touching generic part)? What would be the type of the
val
? Yeah, type with a raw typed generic parameter, which is intentionally not allowed in Kotlin. I think it'd be theorically possible to support such use cases, but I personally don't think it's trivial to implement, and it could lead to increased compiler complexity (let alone IDE plugin) as well as hard to grasp edge cases such as the one I told you
@kassim I don't use
findViewById
anymore, I use a homemade Anko-like View DSL that doesn't need to lookup the View hierarchy: https://github.com/Beepiz/BleGattCoroutines/blob/master/app/src/main/java/com/beepiz/blegattcoroutines/sample/MainActivity.kt#L24 Also, kotlin android extensions cache the views (more efficient than calling the lookup incurring
findViewById
each time) and don't need you to specify the type
k
I’m sure your arguments about complexity are probably valid. But I don’t think this is actually something that’s been settled on by the Kotlin devs, that it will stay this way
l
I think the added complexity into the compiler +IDE plugin to support such feature while avoiding dangerous edge cases that could expose/allow a raw type isn't really worth it considering the few use cases that have easy "workarounds". But if you think it's worth or could help make some code significantly more readable (because this is the point of stripping an explicit generic type, right?), I'd encourage you to add a comment on a related YouTrack issue if there's one on that very same topic, or to open your own on kotl.in/issue
k
Indeed. I think defaulting to the upper bound of the generic type (when possible, and maybe Nothing or some error otherwise) in cases where the explicit type is not specified is something to be desired. I can think of a few cases like those of @kassim’s The link shared by @kirillrakhman definitely gives hope
l
@kassim @kingsley I think the second issue Kirill linked: https://youtrack.jetbrains.com/issue/KT-7590 Is the most desirable. However, you should add your real use cases as comments in the issue to help the Kotlin team decide
👍 1
k
^ good idea 🙂 I will