0

I want to write a function, which needs to use a the class representation of a class declaration like MyClass::class.java.

I have a base class ActivityStarter which I use as a base for companion objects in activities.

// declarations
open class ActivityCompanion<T: AppCompatActivity>(val activityClass : Class<T>) {
    fun startActivity(context: Context) {
        context.startActivity(Intent(context, activityClass))
    }
}

class MyActivity : AppCompatActivity() {
    companion object : ActivityStarter<MyActivity>(MyActivity::class:java)
...
}

// call
MyActivity.startActivity(this)

In the declaration, and the inheritence of the companion object, the class is basically passed twice. Once as type parameter and once as normal parameter. (ActivityStarter<MyActivity>(MyActivity::class:java)).

The parameter activityClass is necessary, because I cant use T::class.java. "Cannot use T as reified type parameter. Use class instead".

I have used to just pass the parameter in the function call:

// declarations
open class ActivityStarter {
    inline fun <reified T : AppCompatActivity>startActivity(context: Context) {
        context.startActivity(Intent(context, T::class.java))
    }
}

class MyActivity : AppCompatActivity() {
    companion object : ActivityStarter()
...
}

// call
MyActivity.startActivity<MyActivity>(this)

This removes the redundancy from the companion object declaration but puts it into the call and basically makes the type parameter in the class useless.

Is there a way to make the type parameter used in the class declaration reified, so that I can have an implementation like this?:

// declarations
open class ActivityCompanion<reified T: AppCompatActivity>() {
    fun startActivity(context: Context) {
        context.startActivity(Intent(context, T::class.java))
    }
}

class MyActivity : AppCompatActivity() {
    companion object : ActivityStarter<MyActivity>()
...
}

// call
MyActivity.startActivity(this)

Or another way to resctict the activityClass parameter so that I can have something like this:

// declarations
open class ActivityStarter(private val activityClass : Class<T : AppCompatActivity>) {
    inline fun startActivity(context: Context) {
        context.startActivity(Intent(context, activityClass))
    }
}

class MyActivity : AppCompatActivity() {
    companion object : ActivityStarter(MyActivity::class.java)
...
}

// call
MyActivity.startActivity(this)
Michael
  • 41,989
  • 11
  • 82
  • 128
Benjamin Basmaci
  • 2,247
  • 2
  • 25
  • 46

1 Answers1

1

Is there a way to make the type parameter used in the class declaration reified

No. But what if you make startActivity not a member of ActivityCompanion, but an extension function so it can have reified type parameters?

class ActivityCompanion<T: AppCompatActivity>()

fun <reified T: AppCompatActivity> ActivityCompanion<T>.startActivity(context: Context) {
    context.startActivity(Intent(context, T::class.java))
}

class MyActivity : AppCompatActivity() {
    companion object : ActivityStarter<MyActivity>()
    ...
}

MyActivity.startActivity(this)

Or another way to resctict the activityClass parameter so that I can have something like this:

If I understood correctly and you want ActivityStarter to accept any subclass of AppCompatActivity without having a type parameter itself, you can write it as

open class ActivityStarter(protected val activityClass: Class<out AppCompatActivity>) { ... }

See official documentation or What is out keyword in kotlin for the meaning of out.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Already thought about that, but I would have liked a more uniform solution. Some of my activities use values, which I pass as parameters in startActivity, so that I can hide the whole intent build up and break down within the activity. – Benjamin Basmaci Aug 13 '20 at 08:21
  • Then maybe the alternative in the edited answer will work for you. – Alexey Romanov Aug 13 '20 at 10:55
  • Exactly what I was looking for. Now when I use this, I only have to pass the Activity Class once when I let a companion object inherit from it. Beautiful! – Benjamin Basmaci Aug 13 '20 at 12:11