What do the brackets mean before the function in Kotlin? - kotlin

What do the brackets mean before a function?
For example:
TextView myTextView = (TextView)findViewById(R.id.tvHello);
Here the (TextView) part is what I have problem with. Is it something like a parameter for
fun <T> findViewByID(...) {...}

First, some history. findViewById used to simply return View, even if the type of the found view was more specific, such as a TextView. So if you wanted to find a view and assign it to a variable with a specific type of View, you would have to cast it to that variable type.
Casting doesn't change the underlying object. It just tells the compiler that you promise that the underlying object already is that more specific type, so the compiler will let you treat it like the more specific type and assign it to a variable of that more specific type.
Your first block of code is Java. The class name in parentheses casts the following expression to a specific class. In Kotlin, you cast by using as, so it would look like:
myTextView: TextView = findViewById(R.id.tvHello) as TextView
However, in later versions of Android and in the support libraries, they changed findViewById to return a generic type T that extends View. This allows Java and Kotlin to implicitly cast the result to the type of the variable you assign the result to. So now you can just use
myTextView: TextView = findViewById(R.id.tvHello)
and it will automatically cast to TextView for you.
When you see code like your first block of code, it probably originated from old code from before the change to findViewById.
Generics are a pretty big topic, and the Kotlin documentation on it is written as if you're already highly familiar with Java generics. So I recommend reading the Java docs on it first, even if you don't really know Java. The explanation will still help you understand what generics do.

It's a cast.
That converts the result of findViewByID to TextView.
Note that with the latest kotlin API that isn't needed. findViewByID has a type parameter T and will automatically return an object of the view type you like.
Once, when that code was written, findViewByID was returning a plain View and callers had to cast it to the desired type.

In this case those brackets that contain (TextView) before the function are used to specify what kind of this you should get when you are done executing the function.
If there is a possible ambiguity about the type of thing you get when you are done executing the function, you do what is called a cast. In this case we cast the returned result to (TextView).
To understand the most basic case of casting I suggest you look at how long/double/float cast in C and Java.

Related

How can I tell the Kotlin compiler that a Java method will never return null?

I don't or can't modify the Java source code. The goal to configure just the Kotlin compiler to know what is nullable and what isn't.
You can specify the type manually if you know something will never be null. For example, if you have the following Java code:
public static Foo test() {
return null;
}
and you call it in Kotlin like this:
val result = Foo.test()
then result will have a type of Foo! by default – which means it can be either Foo or Foo?.. the compiler doesn't have enough information to determine that.
However, you can force the type manually:
val result: Foo = Foo.test()
// use "result" as a non-nullable type
Of course, if at runtime that is not true, you'll get a NullPointerException.
For reference, please check the documentation.
I don't know of a way to configure the compiler for this, but IntelliJ IDEA has a feature that allows you to add annotations to code via an XML file called external annotations.
You can add the Jetbrains #Nullable and #NotNull annotations to library code, but when I've tried it, it only results in compiler warnings rather than errors when you use incorrect nullability in your code. These same annotations generate compiler errors when used directly in the source code. I don't know why there is a difference in behavior.
You can use extension functions for this. If you have a method String foo() in the class Test, you can define the extension function
fun Test.safeFoo(): String = this.foo()!!
The advantage is that the code is pretty obious.
The disadvantage of this approach is that you need to write a lot of boiler plate code. You also have to define the extension function in a place where all your modules or projects can see it. Also, writing that much code just to avoid !! feels like overkill.
It should also be possible to write a Kotlin compiler extension which generates them for you but the extension would need to know which methods never return null.

How to stop Kotlin from widening types?

So I'm trying to define a method like this
fun <R,F> myFunction(prop: KProperty1<R, F>, value:F) {}
// so that the compiler only allows me to invoke it like
myFunction(User::name, "Alejandro")
// and stops developers from doing illegal things like
myFunction(User::name, 123)
//However, compiler doesn't complain if I do that... it widens the type to Any
How can I achieve that?
Kotlin is "widening" the type here because the value type parameter (i.e. the second type parameter) of KProperty1 is defined with keyword out which makes that parameter covariant.
This means that for instance KProperty1<User, String> is a subtype of KProperty1<User, Any>, and hence User::name which is presumably a KProperty1<User, String>, can also be seen as a special case of KProperty<User, Any>. Therefore, it is totally legal to call myFunction<User,Any>(User::name, 123).
The logic behind this can be derived from the name of the out keyword: It is expected that the typed parameter is only used in "out position" of any function call. In the case of KProperty1 this makes sense, because it is the type of the return value of the property. When you get a value from a KProperty1<K, V>, that value is of type V and thus it can be used anywhere where it is okay to have some supertype of V.
This should only be a problem, if you want to use the value in the "in position" of some function, for instance, if you want to write a function that takes a value of type V and store it in a KProperty1<K, V>.
If this is what you want, you are lucky, because you can and should just use KMutableProperty1<K,V> where the value parameter does not have an out keyword which means that it is invariant. Also, that interface allows you to put the value into the property.
Changing your function definition to
fun <R,F> myFunction(prop: KMutableProperty1<R, F>, value:F) {}
makes that the compiler allows myFunction(User::name, "Alejandro"), but it complains on myFunction(User::name, 123).
See also: Kotlin documentation on Variance

What is the scope of casted variable in Kotlin?

When casting a variable at the right side of the assign, i'm surprisely realize that the variable still behave as the casted type and not as it was original defined.
Am i doing something wrong or it's a compiler issue?
Code:
val hippoList = listOf<Hippo>(Hippo())
val hippoMutableList : MutableList<Hippo> = hippoList as MutableList<Hippo>
hippoList.add(Hippo())
since hippoList is from a List type, it is immutable. So how does trying to run add function on an immutable type isn't cause to compilation error?
If you're doing casting it means that you know more than a compiler about this context of execution and you're telling the compiler that this hippoList is a MutableList so on every next usage of hippoList compiler already knows that this have to be a MutableList and allows you to use add method because you casted it to MutableList previously. In fact you will get a runtime error UnsupportedOperationException which means that you didn't really know more about this context of execution and you did something wrong. So instead of using casting on your own allow compiler to do it's work.
In your case instead of a casting to MutableList, transform hippoList to MutableList with
hippoList.toMutableList()
The same happens when you're using !! from nullable type to not null type, when you're using it when you know more than a compiler about the context of execution. Here's a little example
val someNullableType: String? = null
val thisStringIsNotNull = someNullableType!!
by using !! on someNullableType we're telling the compiler that someNullableType is not null as well, so we're allowed to write (as in you're case where you're telling that your List is a MutableList as well)
someNullableType.length
but we will receive exception earlier (in place where we used !! to tweak the compiler)

Same method for nullable and non-nullable arguments

I'm trying to create two almost-same methods that handle nullable and non-nullable arguments slightly differently:
fun parse(type: Any) : MyObject {
return handleParse(type)
}
fun parse(type: Any?) : MyObject? {
if (type == null)
return null
return handleParse(type)
}
But I get this error in Android Studio:
Platform declaration clash: The following declarations have the same JVM signature
The goal is that it automatically handles nullable and non-nullable values in Kotlin, without me using !! every time I call it on nullable terms.
I've already tried adding the #JvmName("-name") annotation as mentioned in this answer but that doesn't work either. Obviously, I can change the method name to something else as well, but that is just circling around and avoiding the issue altogether.
Hoping there's an easy way to do this or at least a sensible workaround. Would also appreciate the reasoning behind the way things currently work, and why I should or shouldn't do this.
Reason why this doesn't work is simple, Java doesn't have null-safe types, meaning that both methods look completely same to Java, and Kotlin aims to provide as much interoperability with Java as possible.
But if you think a bit more about that there is simply no reason for such feature, as you can see your 2nd method already handles everything properly, with addition of 1 if case, which even if this feature exist would have to exist because compiler would need to know whether value in null or not in other to know which method to call anyway.
Common approach that I have seen so far is adding NotNull suffix to your method, for example in your case it would be parseNotNull in case where you don't allow nullable types, this way even when calling code from Java it is clear that parameter shouldn't be null.

Kotlin syntax issue

Sorry for the terrible title, but I can't seem to find an allowable way to ask this question, because I don't know how to refer to the code constructs I am looking at.
Looking at this file: https://github.com/Hexworks/caves-of-zircon-tutorial/blob/master/src/main/kotlin/org/hexworks/cavesofzircon/systems/InputReceiver.kt
I don't understand what is going on here:
override fun update(entity: GameEntity<out EntityType>, context: GameContext): Boolean {
val (_, _, uiEvent, player) = context
I can understand some things.
We are overriding the update function, which is defined in the Behavior class, which is a superclass of this class.
The update function accepts two parameters. A GameEntity named entity, and a GameContext called context.
The function returns a Boolean result.
However, I do not understand the next line at all. Just open and close parentheses, two underscores as the first two parameters, and then an assignment to the context argument. What is it we are assigning the value of context to?
Based on IDE behavior, apparently the open-close parentheses are related to the constructor for GameContext. But I would not know that otherwise. I also don't understand what the meaning is of the underscores in the argument list.
And finally, I have read about the declaration-site variance keyword "out", but I don't really understand what it means here. We have GameEntity<out EntityType>. So as I understand it, that means this method produces EntityType, but does not consume it. How is that demonstrated in this code?
val (_, _, uiEvent, player) = context
You are extracting the 3rd and 4th value from the context and ignoring the first two.
Compare https://kotlinlang.org/docs/reference/multi-declarations.html .
About out: i don't see it being used in the code snippet you're showing. You might want to show the full method.
Also, maybe it is there only for the purpose of overriding the method, to match the signature of the function.
To cover the little bit that Incubbus's otherwise-great answer missed:
In the declaration
override fun update(entity: GameEntity<out EntityType>, // …
the out means that you could call the function and pass a GameEntity<SubclassOfEntityType> (or even a SubclassOfGameEntity<SubclassOfEntityType>).
With no out, you'd have to pass a GameEntity<EntityType> (or a SubclassOfGameEntity<EntityType>).
I guess that's inherited from the superclass method that you're overriding.  After all, if the superclass method could be called with a GameEntity<SubclassOfEntityType>, then your override will need to handle that too.  (The Liskov substitution principle in action!)