【问题标题】:Using type parameter from class declaration like reified type parameter in function使用类声明中的类型参数,如函数中的具体类型参数
【发布时间】:2020-08-12 13:51:01
【问题描述】:

我想写一个函数,它需要使用类声明的类表示,如MyClass::class.java。

我有一个基类 ActivityStarter,我用它作为活动中伴随对象的基础。

// 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)

在声明中,以及伴生对象的继承中,类基本上是传了两次。一次作为类型参数,一次作为普通参数。 (ActivityStarter&lt;MyActivity&gt;(MyActivity::class:java))。

参数activityClass是必须的,因为我不能使用T::class.java。 “不能将 T 用作具体类型参数。请改用类”。

我以前只是在函数调用中传递参数:

// 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)

这消除了伴随对象声明中的冗余,但将其放入调用中,基本上使类中的类型参数无用。

有没有办法让类声明中使用的类型参数reified,这样我就可以有这样的实现了?:

// 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)

或者另一种方法来限制activityClass参数,这样我就可以拥有这样的东西:

// 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)

【问题讨论】:

    标签: kotlin generics inheritance


    【解决方案1】:

    有没有办法使类声明中使用的类型参数具体化

    没有。但是,如果你让startActivity 不是ActivityCompanion 的成员,而是一个扩展函数,所以它可以具有具体的类型参数呢?

    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)
    

    或者另一种方法来限制activityClass参数,这样我就可以拥有这样的东西:

    如果我理解正确并且您希望ActivityStarter 接受AppCompatActivity 的任何子类而本身没有类型参数,您可以将其写为

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

    请参阅official documentation 或What is out keyword in kotlin 了解out 的含义。

    【讨论】:

    • 已经考虑过了,但我希望有一个更统一的解决方案。我的一些活动使用值,我将其作为参数传递给 startActivity,这样我就可以隐藏活动中构建和分解的整个意图。
    • 那么也许编辑后的答案中的替代方案对你有用。
    • 正是我想要的。现在当我使用它时,我只需要传递一次 Activity 类,当我让一个伴随对象继承它时。漂亮!
    猜你喜欢
    • 1970-01-01
    • 2016-07-21
    • 2012-02-16
    • 2011-10-02
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2020-10-11
    相关资源
    最近更新 更多