in the below 2 posted examples, i am trying to convert the java code to kotlin code.
the kotlin code does not work and IntelliJ says that I should use companion object.
please let me know how to correct this error.
code_kotlin*
#SpringBootApplication
class MyApplication {
}
fun main(args: Array<String>) {
SpringApplication.run(MyApplication::class.java, *args)
}
codeJava
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Include main function inside Application class, as Java code does:
#SpringBootApplication
class MyApplication {
fun main(args: Array<String>) {
SpringApplication.run(MyApplication::class.java, *args)
}
}
Unlike Java or C#, Kotlin doesn’t have static members or member functions. Kotlin recommends to simply use package-level functions instead. For more detail you can get help from link. You can call companion object like-
class YourClassName{
companion object {
//write what you want to make static
}
}
Related
I am trying to create a test class with an inner class but I am getting an error "companion object is not allowed here". What is supposedly be the problem? Please see my sample code snippet below. And also i am using JUnit4 for this development.
#RunWith(Enclosed::class)
class OuterUnitTest{
#RunWith(Parameterized::class)
inner class Inner1UnitTest {
#Test
fun testInner1(){
// test code here
}
companion object{
#JvmStatic
#Parameterized.Parameters
fun testData() : Any? {
return something
}
}
}
}
It's hard to explain but I basically want to be able to have an interface which my subclasses need to implement, which mandates a static constant. How would I achieve this in Kotlin?
I have the following class/interface:
interface BaseFragmentInterface {
val TAG: String
}
class BaseFragment: Fragment() {
/* this, of course, doesn't compile right now: */
companion object: BaseFragmentInterface {}
func<T: BaseFragment> push(fragment: T) {
/* Here I want to access TAG */
Log.d(T.TAG, "Push Fragment")
}
}
My subclasses need to be required to implement the interface. And my base companion object would need to be somehow abstract.
Any idea how to achieve this?
Let me precise few things.
My subclasses need to be required to implement the interface.
There's no way to achieve this, you can't force a subclass' companion object to implement your interface since the companion object of a class is not related to the companion object of its superclass.
And my base companion object would need to be somehow abstract.
Since the companion object is an object, it can't be abstract, because an object can't be abstract too.
Said that, you have two options to still achieve your desired behavior:
Use TAG as a non-static final property inside BaseFragment:
abstract class BaseFragment : Fragment() {
protected abstract val TAG: String
fun <T : BaseFragment> push(fragment: T) {
/* Here I want to access TAG */
Log.d(TAG, "Push Fragment")
}
}
class FragmentImpl : BaseFragment() {
override val TAG: String = "fragment-impl"
}
Use companion objects to hold the tag, make the type T of push() as reified and access the TAG property inside the companion object of T using the reflection.
I'm migrating part of application from Java to Kotlin and have a question about that.
What is preferable or better way ?
File with annonation #file:JvmName and funtion inside
#file:JvmName("ClassX")
fun funX() {}
or
Typical class with #JvmStatic annotation inside companion object
class ClassX {
companion object {
#JvmStatic
fun funX() {}
}
}
Let's look at the decompiled code to answer this question.
Kotlin file with a #JvmName annotation like yours:
#file:JvmName("ClassX")
fun funX() {}
will be compiled into a bytecode, analogous to this Java code:
#JvmName(
name = "ClassX"
)
public final class ClassX {
public static final void funX() {
}
}
Pretty similar to what you'd probably write when using Java, right?
A Kotlin class with a companion object like this:
class ClassX {
companion object {
#JvmStatic
fun funX() {}
}
}
is analogous to this Java code:
public final class ClassX {
public static final ClassX.Companion Companion = new ClassX.Companion((DefaultConstructorMarker)null);
#JvmStatic
public static final void funX() {
Companion.funX();
}
public static final class Companion {
#JvmStatic
public final void funX() {
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
As you see, class with a companion object will generate more code.
Is it good or bad? You decide. I'd say it's bad and it's better to use a file with #JvmName annotation. There is also a discussion on Kotlin's forum about this topic: read the best practices.
BTW, you can look at the bytecode and decompiled Java code in IntelliJ IDEA via "Tools" -> "Kotlin" -> "Show Kotlin Bytecode".
I have a few cases where I want to add static functions or values in a base class so that I can use them in all subclasses that inherits from it.
One such case is when i want to create generic tags for each class to use in data mapping as a key, like when i want to find fragments or pass data between activities.
For example:
open class BaseClass(){
companionObject{
val TAG: String = this.javaClass.simpleName
}
}
class ChildClass: BaseClass()
class Main: Activity(){
fun startActivity(){
val intent = Intent(this, ChildClass::class.java)
intent.putExtra(ChildClass.TAG, data)
startActivity(intent)
finish()
}
}
Can this be done or am I forced to create an companion object for each class?
I don't know a solution with companions. But you could use a global reified inline function for the specific use case, you mentioned in your question:
open class BaseClass()
class ChildClass: BaseClass()
inline fun <reified T> tagOf() = T::class.java.simpleName
fun main(args: Array<String>) {
println(tagOf<BaseClass>())
println(tagOf<ChildClass>())
}
Hm... I think, you can't do it. As mentioned in this article: https://proandroiddev.com/a-true-companion-exploring-kotlins-companion-objects-dbd864c0f7f5
companion object is really a public static final class in your BaseClass. So, I think, you can't do this.
I use this code to add extension for Log class android
fun Log.i2(msg:String):Unit{
Log.i("Test",msg)
}
when using in the activity
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.i2("activity_main")
}
}
Log.i2 not found. What's wrong?
To achieve extension function in static class, you need to write extension of the companion object(refer this)
fun Log.Companion.i2(msg:String) {
...
}
You have created Extension function of Class Log.
Which is suppose to call by Instance of Class Log. You are trying to treat extension function as static and calling it by Class name. Which is not correct in the case
Currently, static extension methods in Kotlin is not supported without the companion object, because android.util.Log is a java class, so there is no companion object.
Instead, I recommend you to use a static function (package-level function, simply declared outside a class in a source code file):
fun logI2(msg: String) {
Log.i("Test", msg)
}
And just use it like this:
logI2("activity_main")