Classifier does not have a companion object, and thus must be initialized here

61,026

Solution 1

This line selection=RowSubTShirtViewModel references the view model as if it were a named object, meaning you would have written instead of class object:

object RowSubTShirtViewModel {
   //...
}

However, since that's not the case, kotlin is telling you that you cannot reference it like that and must initialize it. The constructor as quite a lot of parameters for me to guess what they are, but essentially you'd have to pass them in:

selection=RowSubTShirtViewModel(/*parameters here*/)

Solution 2

Having a companion object (and having members in that companion object) in Kotlin is equivalent to having static members (static methods or fields) in Java, and as it is known, static members in Java can be accessed without initializing the class or having a reference to an object of that class. For example, given:

// this is Java
class A {
  static void s() {System.out.println("static");}
  void d() {System.out.println("dynamic");}
}

we could call the s() method without initializing the class A, like this: A.s();, and it would print "static", but in order to be able to call the d() method, we need an object of the A class, which we can get by either initializing it elsewhere like this: A a = A();, and then doing a.d(); or doing them together like this: A().d();, both of which would print "dynamic".

Even though Kotlin does not have the static keyword, it must have the same functionality since any Java code can be translated into Kotlin code. Now when we want to transfer this train of thought into Kotlin, we would instead say something like "in order to use members from the companion object (static members, basically), you must initialize the class name (i.e. create an object)".

So when Kotlin complains and says Classifier Something does not have a companion object, and thus must be initialized here, it is basically telling you that that class does not have any static members (since it does not have a companion object), and so if you want to use it, either use it with parenthesis (initialize it to create an object of it), or declare a companion object in it (using the companion object keyword).

I hope this clears things up. Sadly, uninformative messages like this prove that you need prior Java understanding to learn Kotlin, a fact that haunts it and will hinder its ability to stand alone as a language.

Share:
61,026
Farhana Naaz Ansari
Author by

Farhana Naaz Ansari

Farhana... The only way of writing fewer bugs is writing less code.

Updated on April 22, 2022

Comments

  • Farhana Naaz Ansari
    Farhana Naaz Ansari about 2 years

    I have an Activity where an interface is declared and I have a ViewModel class which has overridden interface and want to invoke the method of interface from Activity to make changes in ViewModel class but unable to call method in Activity saying ViewModel class does not have a companion object, and thus must be initialized here. How to resolve this?

    var selection: setSelectionSubRow? = null
        selection=RowSubTShirtViewModel
        selection!!.setNameSelection(false)
    

    above code is in Activity whose name is TShirtActivity.

    below code is from RowViewModel class

    class RowSubTShirtViewModel(private val subTShirtAdapter: SubTShirtAdapter, val context: TShirtActivity,
                            val tShirtBean: CommonItemBean, private val parentPosition: Int, private val position: Int) : BaseObservable() ,TShirtActivity.setSelectionSubRow{
    
    fun getImageDrawable(): Drawable {
        return if (tShirtBean.isSelected)
            ContextCompat.getDrawable(context, R.drawable.green_border_circle)!!
        else
            ContextCompat.getDrawable(context, R.drawable.border_circle)!!
    }
    
    override fun setNameSelection(selection: Boolean) {
        if (parentPosition == 6) {
            if (position == 1) {
                tShirtBean.isSelected = false
            }
        }
    }
    
  • Farhana Naaz Ansari
    Farhana Naaz Ansari over 5 years
    I got your point. but other problems have to face, Actually this RowSubTShirtViewModel is a viewmodel of subAdapter class and it is using in ViewModel class of Activity and there is a dialog in activity, in dialog on button click I want to reverse selection of RecycleView item and the RowSubTShirtViewModel is a viewModel for the adpater of that recyclerview, so how can i manage constructor of RowSubTShirtViewModel in Acitivty
  • Fred
    Fred over 5 years
    That's just a classic dependency problem. You just carry on passing everything until you have all you need. For example, if you construct RowSubTShirtViewModel in the adapter, which is used in an activity, then you can pass the activity as you instantiate the adapter and then pass it in as you instantiate RowSubTShirtViewModel. There are other approaches using dependency injection frameworks like Dagger. I can't really tell you what suits you best, but the problem you're having will always lead to having to build RowSubTShirtViewModel.
  • Farhana Naaz Ansari
    Farhana Naaz Ansari over 5 years
    Thanks Fred I will look both the solutions.