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.
Related
What I can understand from google documentation is that we can use inline keyword to enhance the performance and reduce the memory allocation on runtime in case of high order function but why in this case we are inlining a variable
#PublishedApi
internal inline val <T : Any> T.loggingTag: String
get() {
val tag = this::class.java.name.substringAfterLast(".")
if (tag.contains("$")) {
return tag.substringBefore("$")
}
return tag
}
in case you are curious the logging tag variable is used in an inline function
inline fun <reified T : Any> T.errorLog(error: Throwable? = null, message: String? = null) {
errorLog(loggingTag, error, message)
}
also the errorLog function inlined even it doesn't take an other function as a parameters does anyone able to explain for me this ?
inline fun errorLog(tag: String, error: Throwable? = null, message: String? = null) {
Timber.tag(tag).e(error, message)
}
That val isn't a variable. It's a property. If you see val or var outside of a function, it's a property, not a variable.
Properties have getter functions. In your example, the getter function is what is being marked as inline.
There are two main reasons to use inline functions:
In a higher order function, it avoids allocating a function object to represent the function parameter (lambda or function reference) being passed to it. It also allows lambdas that are passed to use keywords that are normally restricted to local use, such as return, break, and continue.
It is necessary for reified generics. If a function needs to be able to inspect one of its generic types, the type needs to be marked as reified, which in turn requires the function to be marked inline.
Generally, you want to avoid using inline if a function doesn't fit one of the above cases, because actual function calls themselves are rather trivial, and if you inline a function that is used frequently (the only kind of function you would want to be optimized), then its code is going to be repeated everywhere it's used in your compiled app, increasing the size of the app.
An exception might be if the inline function contains only one function call, so it's not really increasing code size.
I do not see any reason the inline keyword is needed for the extension property in your first block of code. It is not a higher-order function, and it is a multi-line function. I also don't see why it is defined as a generic function, since the type T is not used for anything inside the function. I think I would define it as:
internal val Any.loggingTag: String
Also, in your second block of code, I don't see any reason why there is a generic type, since it is not used in that function. It could be defined as:
fun Any.errorLog(error: Throwable? = null, message: String? = null) {
The third block of code doesn't benefit much from inlining either. It's not a higher-order function. If function call overhead is that much of an issue for performance, it would make more sense to fork Timber and rewrite how it creates tags, because using custom temporary tags like that in Timber involves a few method calls under the hood.
The inline keyword is used to make functions inline, meaning that when a function is called, its body is copied and pasted into the caller's code instead of making a function call. This allows for reduced execution time, as there is no need to jump to another function and back. Inline functions can also be used to reduce code size and improve readability.
Passing a lambda to the last parameter
In Kotlin, there is a convention that if the last parameter of a
function accepts a function, a lambda expression that is passed as the
corresponding argument can be placed outside the parentheses:
val product = items.fold(1) { acc, e -> acc * e }
What is the purpose of this syntax?
This syntax gives Kotlin great DSL capabilities, it makes functions look like language constructions. For example:
with(car) {
startUp()
goToDestination()
}
Here with looks like it is language construction, whereas it is a simple function, receiving lambda as the last parameter.
And this leads to such elegant things like Kotlin HTML DSL
I am thinking about vararg (variable arguments) option in kotlin. I know it was here before kotlin in time of java, but I actually never really understand benefit of using it. If i want for example for my function myFun() to take variable number of arguments (let's say Strings), I would create myFun() in a way that it takes List of Strings. I don't see any reason for using vararg.
Is there any benefit of using vararg over List, am I missing something?
vararg gives you freedom to call a function with infinite number of arguments without wrapping them in a collection. Using argument of List type, you are in control of more than just arguments, such as mutability.
This is more opinioned answer.
You are right, passing a list is one option to avoid vararg.
For you as the implementor of the function there is no real difference, but for the consumer it is. It's a question of function design. How do you want your clients to call your functions.
Passing a list forces the caller to create a list first and populate it with all the items before passing them to the function.
fun foo(list: List<Int>) { ... }
val list: List<Int> = listOf(1,2,3,4,5)
foo(list)
If you offer a function taking a vararg type the way how to call that function changes.
fun bar(vararg items: Int) { ... }
fun bar(1) // just passing one parameter
fun bar(1,2,3) // or maybe three, etc.
Both ways have their usecases.
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}")
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()