I'm trying to do something like:
val barcodes = arrayOf("123", "456", "789")
realm.where(Product::class.java).in("barcode", barcodes).findAll()
However "in" is a Kotlin function and I can't access the in(String filedName, String[] values) method of RealmQuery object.
Currently I have a java class that does the job and returns the result, but I was wondering is there a more graceful workaround for this?
As stated in the Escaping for Java identifiers that are keywords in Kotlin:
Some of the Kotlin keywords are valid identifiers in Java: in, object,
is, etc. If a Java library uses a Kotlin keyword for a method, you can
still call the method escaping it with the backtick (`) character
For example:
realm.where(Product::class.java).`in`("barcode", barcodes).findAll()
Related
In JavaScript, there's a regex function: RegExp test() which gets used a bit like this:
new RegExp('/regex/').test('string to match')
What this does is it tests for a match in a string. If it finds a match, it returns true, otherwise it returns false.
But I can't seem to find an equivalent on Kotlin, Android. Does anyone know if there's something like this or similar on Kotlin?
You can use the contains extension on CharSequence:
"string to match".contains(Regex("regex"))
Or the containsMatchIn method on Regex:
Regex("regex").containsMatchIn("string to match")
This might be a very silly question, but I am logging the methods that are triggered in my app as strings. When an issue is submitted, I would like to automatically input the text of the strings as parameters for methods. E.g:
For method:
fun assignPot(potType: PotType, ball: DomainBall, action: PotAction) {...}
I'd like to somehow call method:
assignPot(FOUL(2, BLUE(5), SWITCH))
From String:
"FOUL(2, BLUE(5), SWITCH)"
The only workaround I can think of is to split the string and create a when -> then function to get actual classes from strings, but I wondered if there's a more concise way for this.
This is not what you want to do. You should design your app in a way that prevents users from providing input similar to actual code.
However, you can achieve this. Complex parsings like this oftenly use regex-based approaches.
As you said, you should map your string part to class. If your PotType is enum, you can do something like
val re = Regex("[^A-Za-z\s]")
val reNumbers = Regex("[^0-9\s]")
// get classes
val classNames = originalString.replace(re, "").split(" ")
// get their constructor numerical arguments
val classArgs = originalString.replace(reNumbers, "").split(" ")
After that you can implement mapping with when expression. You probably will use some collection of Any type.
As you see, this sadly leads you to parsing code by code. Concise way to solve is to implement your own script compiler/interpreter and use it in your application :) That will later lead you to dealing with security breaches and so on.
If you are logging problematic method calls and want to repeat them immediately after issue is submitted, you probably want to programatically save the calls to lambdas and call them when you receive an issue log.
I've seen people using ViewModelProvider[Someclass::class.java] instead of ViewModelProvider.get(Someclass::class.java), and it compiles in Android Studio. The problem is that I couldn't find any documentation of such usage online.
With kotlin you can add operator modifiers to your function. So if you have some class with a get function and you might want to access it with [], like an array or map, you could add operator modifier.
Square brackets are translated to calls to get and set with appropriate numbers of arguments.
So this only works for functions with name get or set!
class Provider {
operator fun get(key: String)
operator fun set(key: String, value: String) { ... }
}
Then you can call the function like:
Provider().get("key") // IDE hint: should be replaced with indexing operator
Provider()["key"] // calls get()
Provider().set("key", "value") // IDE hint: should be replaced with indexing operator
Provider()["key"] = "value" // calls set()
Reference
See Kotlin Operator overloading
Kotlin allows operator overloading by marking a function as an operator function. The square brackets notation is one of these operators (indexed access operator).
Kotlin automatically interprets Java functions as operator functions if their name and signature match the requirements of a Kotlin operator function. In this case, it interprets functions named get as an "indexed access operator" if they return something, which allows you to use square bracket notation.
ViewModelProvider[Someclass::class.java] is a shorter version of ViewModelProvider.get(Someclass::class.java) there is no differences.
In C# we have nameof() operator which return name of the class in string, what is the equivalent in Kotlin?
My use case would be something like this for
internal val TAG = nameof(MyCustomActivity)
MyCustomActivity::class.simpleName
Will output MyCustomActivity
MyCustomActivity::class.qualifiedName
Will output <your_package>.MyCustomActivity
As mentioned in the accepted answer, the <class>::class.simpleName property will provide a result similar to that of the C# nameof operator. However, unlike nameof, ::class.* cannot be evaluated at compile-time.
This is relevant, as cases where you may use the nameof operator in C#, you cannot equivalently do with ::class
For example, AspectJ's #Around annotation.
The following will fail, as you cannot interpolate non-compile-time† expressions:
#Around("#annotation(${MyAnnotation::class.simpleName})")
If Kotlin supported nameof in the same fashion as C# (where it can be used in that context) one could do this:
#Around("#annotation(${nameof(MyAnnotation)})")
So, while the accepted answer provides a functionally similar manner of resolving symbol names in Kotlin, it cannot be used with the same flexibility as nameof in C#.
† Interestingly, until writing this answer I didn't realize you can interpolate constant value (and other compile-time evaluable) expressions into annotation parameters; the following will compile:
const val FOO = "foo"
#MyAnnotation("${FOO} ${1 + 1}")
This is my data class created using a Kotlin data class creator Plugin.
data class ResponseHealthInisghts(
val `data`: List<Data>,
val message: String,
val statusCode: Int
)
This code gets work even if I remove the backticks, I wonder if it's for Java interoperability. But this variable is not a keyword but also it has backticks. why?
Based on Why does this Kotlin method have enclosing backticks?
this question is is a keyword for both Java and Kotlin but data is not.
You can use backticks simply to enclose class, method or variable name
For example it's useful if there are spaces:
class `Final Frontier` {
fun `out of space`() {
val `first second`: String?
}
}
Or as you mention if using Kotlin keyword
If a Java library uses a Kotlin keyword for a method
foo.`is`(bar)
data is a Modifier Keyword
data instructs the compiler to generate canonical members for a class
The following tokens act as keywords in modifier lists of declarations and can be used as identifiers in other contexts
And not a Hard Keyword that can't be used as identifier
The following tokens are always interpreted as keywords and cannot be used as identifier
It allows you to use reserved keywords and operators as names of your variables. The list of those words: https://kotlinlang.org/docs/reference/keyword-reference.html
Based on this question's answerWhy does this Kotlin method have enclosing backticks?
and the comments from #forpas and #marstran I was able to understand my problem.
The is keyword is a hard keyword
Hard Keywords
are always interpreted as keywords and cannot be used as identifiers:
so fore interoperability we need to use backticks because Java and Kotlin both have is keyword.
Where data keyword is only available in Kotlin and also belong to the category
Soft Keywords
act as keywords in the context when they are applicable and can be used as identifiers in other contexts.
So we can use it with or without backticks.
Also as an additional note you can use bacticks to customize your identifier
var `data is simple` : List<String>
If it shows lint error use
"File | Settings | Editor | Inspections | Illegal Android Identifier" and disable this inspection.