Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I define constants in an inner class?

Tags:

android

kotlin

I have the following code in Java which I want to convert to Kotlin:

class RideHistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    class HistoryItemHolder extends RecyclerView.ViewHolder {
        private static final int TYPE_IN_PROGRESS = 1
        private static final int TYPE_CANCELLED = 2
        private static final int TYPE_FINISHED = 3

        // class methods and properties are written
    }
}

I have come up with the following code:

class RideHistoryAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private inner class HistoryItemHolder(view: View)
        : RecyclerView.ViewHolder(view) {
        private companion object {
            private const val TYPE_IN_PROGRESS = 1
            private const val TYPE_CANCELLED = 2
            private const val TYPE_FINISHED = 3

            // class methods and properties are written
        }

    }

}

Android Studio is showing a red squiggly under "object" of the line companion object, saying:

Companion object is not allowed here

Note: I know I can convert it to non-inner class but I'd prefer keeping it one. I also checked I can't define an interface in an inner class too.

like image 786
Sufian Avatar asked Jan 01 '23 16:01

Sufian


2 Answers

First of all you Java is not valid. If you fix it you get an error: Inner classes can not have static declarations

invalid java

You cant have a companion object in an inner class for the same reason that you can not have static members in an inner class in java

https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html:

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.

(highlight by me)

With the same reasoning it does not make sense to have a quasi-static companion object associated with instance.

Solutions (pick one):

  1. use val (similar to final).
  2. move the companion object to the enclosing class.
  3. make HistoryItemHolder not an inner class.
like image 132
leonardkraemer Avatar answered Jan 04 '23 16:01

leonardkraemer


I can confirm that it is not possible to add constants in an inner-class (see my question on Kotlin forums).

However, there are two ways you can go about (I chose the first):

  1. Make ViewHolder a non-inner class - this means it can no longer access methods/properties of Adapter:

    public class Adapter {
    
        public class ViewHolder(private val adapter: Adapter) {
    
            private companion object {
                private const val TYPE_IN_PROGRESS = 1
                private const val TYPE_CANCELLED = 2
                private const val TYPE_FINISHED = 3
            }
        }
    }
    
  2. Define constants in the Adapter:

    public class Adapter {
        private const val TYPE_IN_PROGRESS = 1
        private const val TYPE_CANCELLED = 2
        private const val TYPE_FINISHED = 3
    
        public class ViewHolder(private val adapter: Adapter) {
            // ..
        }
    }
    

Note: do not convert your const val to val as it will bind it to your class instance (which is bad. More about it here).

like image 44
Sufian Avatar answered Jan 04 '23 15:01

Sufian