I\'m creating my first Kotlin classes in my Android application. Usually for logging purposes I have a constant with name TAG
. What I would do in Java is:
Here is my extension function in kotlin, just add it in your extensions file.
val Any.TAG: String
get() {
return if (!javaClass.isAnonymousClass) {
val name = javaClass.simpleName
if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name else
name.substring(0, 23)// first 23 chars
} else {
val name = javaClass.name
if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
name else name.substring(name.length - 23, name.length)// last 23 chars
}
}
Then you can use TAG in any class like below:
Log.d(TAG, "country list")
In Kotlin you could create an extension, and call tag as a method call instead. This would mean you'd never have to define it inside each class, we can construct it dynamically each time we call the method:
inline fun <reified T> T.TAG(): String = T::class.java.simpleName
I Like TAG
to be an extension function as suggested by Fredy Mederos.
extending his answer to support anonymous classes :
/**
* extension function to provide TAG value
*/
val Any.TAG: String
get() {
return if (!javaClass.isAnonymousClass) {
val name = javaClass.simpleName
if (name.length <= 23) name else name.substring(0, 23)// first 23 chars
} else {
val name = javaClass.name
if (name.length <= 23) name else name.substring(name.length - 23, name.length)// last 23 chars
}
}
In Android Studio, the usual way to rename something is to right-click the name, select Refactor->Rename. So, I think it's fine to do something like this,
class MyClass {
companion object {
private const LOG_TAG = "MyClass"
}
}
because if you rename the class MyClass
like I described, then the IDE will suggest renaming your LOG_TAG String as well.
Ultimately there are pros and cons of using this method vs. other methods. Because LOG_TAG is a String, there's no need to import the kotlin-reflect.jar, as you would if you set LOG_TAG
equal to MyClass::class.simpleName
. Also because the variable is declared as a compile-time constant with the const
keyword, the generated bytecode is smaller since it doesn't need to generate more hidden getters, as described in this article.
I found a way which is more "copy-paste"-able, since it doesn't require you to type the name of your class:
package com.stackoverflow.mypackage
class MyClass
{
companion object {
val TAG = this::class.toString().split(".").last().dropLast(10)
}
}
It's not the most elegant solution but it works.
this::class.toString().split(".").last()
will give you "com.stackoverflow.mypackage.MyClass$Companion"
so you need the dropLast(10)
to remove $Companion
.
Alternatively you can do this:
package com.stackoverflow.mypackage
class MyClass
{
val TAG = this::class.simpleName
}
But then the TAG
member variable is no longer "static" and doesn't follow the recommended naming conventions.
In general constants are all caps (ex. FOO) and located in the companion object:
class MyClass {
companion object {
public const val FOO = 1
}
}
and to define the TAG field you can use:
private val TAG = MyClass::class.qualifiedName