I need to use configuration objects in my code. I have a typealias as follows:
typealias MyParam = Triple<String, Any, Type>
I then have a list of these which is populated at runtime:
val paramsList: MutableList<MyParam> = mutableListOf();
Now when I try and populate the list, I get an error:
paramsList.add(Triple("Strength", 0, Float))
It says "Type mismatch: required Type. Found Float.companion".
How can I get around this error? I will eventually need to cast a value using this Type.
You can use ::class to refer to Kotlin's KClass and use the .java property to get Java's Class out of it (which implements Type):
paramsList.add(Triple("Strength", 0, Float::class.java))
For more complex types with generics like List<Float>, use typeOf<List<Float>>() which gives you the KType corresponding to List<Float>, and then javaType to get a Type out of it:
import kotlin.reflect.typeOf
import kotlin.reflect.javaType
paramsList.add(Triple("Strength", 0, typeOf<List<Float>>().javaType))
You could try calling a list with float types.If you get an error, share the error code and I'll help you.
Related
I'm trying to do something from a guide I found online, which is passing a generic type variable to the Json function encodeToString(), I do not want to use a reified type, but it does not work for me...
Here is my sample code:
fun <G> encodetojson(toConvert: G){
converted = Json.encodeToString(toConvert)
return converted
}
From the above code I get a type mismatch error.
How I might fix this?
In Kotlin i am learning about covariant(a subtype can be used in place of a super type).
They wrote there something like a rule. but it seems wrong for me. It is written:
You can’t, however, use out if the class has function parameters or var
properties of that generic type.
But i think that the word or should be replaced with the word and, because in situation when a class has a function that "gets" the type as a parameter, if the property of the generic type is a val and not var, and damage can't be done, because any assignment isn't possible to val property.
Am i right or what is written in the book is correct and i'm missing something?
Edit:
I just realized (according to some post i saw in this forum) that the only situation that a parameter can be a problem although property is declared as val, is in case we have a container of type T, let's say List then it may be a problem if we try to add to the List, but if we don't have a container i can't see situation when getting a parameter type can make trouble while property is val. Am i right?
The out keyword is for covariance, not contravariance.
Here's a basic example of the trouble caused in an imaginary class where covariance is allowed for the var property type:
class Container<out T>(var item: T)
val intContainer = Container<Int>(1)
val numberContainer: Container<Number> = intContainer // cast is allowed for covariant type
numberContainer.item = 5f // allowed if item is a var
val intValue = intContainer.item // Float value is cast to an Int!
This isn't possible with a val so the above class could be covariant at the declaration site if item were a val.
I'm trying to send MutableList<Point> array list as Extra from Intent to another in kotlin.
Declaring the list:
private var thePoints: MutableList<Point> = mutableListOf()
and here is how I add items to it:
if (startStationPoint != null) {
thePoints.add(startStationPoint)
}
And am using this method to send it to the other Activity:
navigationActivity.putParcelableArrayListExtra(
"thePoints",
thePoints)
It gives me this error:
Type mismatch:
Required: ArrayList<out Parcelable>!
Found: MutableListM<Point>
as am using putParcelableArrayListExtra as there is no such thing to put points arraylist extra.
The error explains you are using as argument a mutable list but you have to use an array
thePoints.toList().toTypedArray()
I'm not sure if that will work because Point can not meet the conditions
You could create a class representing the point
data class SerializablePoint(val longitude: Long, val latitude: Long) : Serializable
And then use .map to convert them.
Or you could do the same with parceleable.
Another options is to try Pair which is Kt API, but again I don't know if parcealability or serializability conditions are complied.
To figure it out ctrl+click on any of those classes and see if in any point implements serializable or parceleable, otherwise transforming to a custom class will be needed.
you can use Google Gson to convert the object to a string and then pass it as a string.
from the receiving end convert the string to your original object.
Refer this ->
https://stackoverflow.com/a/33381385/9901309
I'm new to Kotlin
I used this code for opening another activity:
startActivity(Intent(this,IntroAndLang::class.java))
current activity and target activity are written in Kotlin
I can't understand why there is not single : instead of :: at IntroAndLang::class.java
:: is used for Reflection in kotlin
Class Reference val myClass = MyClass::class
Function Reference this::isEmpty
Property Reference ::someVal.isInitialized
Constructor Reference ::MyClass
For detailed reading Official Documentation
:: converts a Kotlin function into a lambda.
Let's say you have a function that looks like this:
fun printSquare(a: Int) = println(a * 2)
And you have a class that takes a lambda as a 2nd argument:
class MyClass(var someOtherVar: Any, var printSquare: (Int) -> Unit) {
fun doTheSquare(i: Int) {
printSquare(i)
}
}
How do you pass the printSquare function into MyClass? If you try the following, it wont work:
MyClass("someObject", printSquare) //printSquare is not a LAMBDA, it's a function so it gives compile error of wrong argument
So how do we CONVERT printSquare into a lambda so we can pass it around? Use the :: notation.
MyClass("someObject",::printSquare) //now compiler does not complain since it's expecting a lambda and we have indeed converted the `printSquare` FUNCTION into a LAMBDA.
Also, please note that this is implied... meaning this::printSquare is the same as ::printSquare. So if the printSquare function was in another class, like a Presenter, then you could convert it to lambda like this:
Presenter::printSquare
UPDATE:
Also this works with constructors. If you want to create the constructor of a class and then convert it to a lambda, it is done like this:
(x, y) -> MyClass::new
this translates to MyClass(x, y) in Kotlin.
As stated in the docs this is a class reference:
Class References:
The most basic reflection feature is getting the runtime reference to a Kotlin class. To obtain the reference to a statically known Kotlin class, you can use the class literal syntax:
val c = MyClass::class
//The reference is a value of type KClass.
Note that a Kotlin class reference is not the same as a Java class reference. To obtain a Java class reference, use the .java property on a KClass instance.
It’s also the syntax for method references as in this simple example:
list.forEach(::println)
It refers to println defined in Kotlin Standard library.
Since kotlin 1.1, in addition to class, function, property and constructor references as stated above, '::' can also be used to obtain the bound references to all of the above.
For instance, using '::class' could be used to get the exact class of a particular object despite the type of the receiver as below...
val widget: Widget = ...
assert(widget is GoodWidget) { "Bad widget: ${widget::class.qualifiedName}" }
widget::class returns the exact class of the object 'widget' as either 'GoodWidget' or 'BadWidget' despite the type of the receiver expression (i.e 'Widget' as declared initially)
More info at https://kotlinlang.org/docs/reference/reflection.html
I'm trying to mock a function in Kotlin
Mockito.mock(Function2<Int, Int, Unit>::class.java)
and it says "Only classes are allowed on the left hand side of a class literal". What's the proper way to obtain a reference to a statically known parameterized class? For now I live with an ugly cast
Mockito.mock(Function2::class.java) as (Int, Int) -> Unit
The error is correct and the solution you provided is the intended one. The rationale here is that since generic type arguments are not reified at runtime, you can only obtain an object representing a class, not a type.
There's a workaround though: if you use the class literal syntax through a reified type parameter, substituting it with the desired type at the call site, you'll get the same KClass object but with the actual arguments you've provided. In your case you can declare the following function:
inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java) as T
And use it like this:
val f = mock<(Int, Int) -> Unit>()