让非泛型类在构造函数中使用泛型参数

时间:2016-02-04 19:50:26

标签: generics kotlin

我想在kotlin中有一个非泛型类,它在构造函数中使用泛型来指定一个参数。但是,我无法弄清楚如何做到这一点,并且Intellij的Java-to-Kotlin转换器会中断。

我的java类看起来像这样

public class Test {    
    interface I1 { }    
    interface I2 { }

    private final I1 mI1;
    private final I2 mI2;

    public <T extends I1 & I2> Test(T host) {
        mI1 = host;
        mI2 = host;
    }
}

转换器的输出如下所示。

class Test(host: T) where T: I1, T: I2 {
    internal interface I1
    internal interface I2

    private val mI1: I1
    private val mI2: I2

    init {
        mI1 = host
        mI2 = host
    }
}

我想这样做,因为在Android开发中,能够指定看起来像<Host extends Context & CustomCallbackInterface>

的构造函数参数很有用。

2 个答案:

答案 0 :(得分:6)

看着Kotlin的Bluebird docs,目前看来这是不可能的。对于主构造函数,类型参数表示类类型参数:

class (used by memberDeclaration, declaration, toplevelObject)
  : modifiers ("class" | "interface") SimpleName
      typeParameters?
      primaryConstructor?
      (":" annotations delegationSpecifier{","})?
      typeConstraints
      (classBody? | enumClassBody)
  ;

对于辅助构造函数,没有可能的类型参数:

secondaryConstructor (used by memberDeclaration)
  : modifiers "constructor" valueParameters (":" constructorDelegationCall)? block
  ;

但是,构造函数只是一个特殊的函数。如果我们不使用构造函数,而是使用我们自己的函数,我们可以提出以下内容:

class Test {

    interface I1

    interface I2

    private val mI1: I1
    private val mI2: I2

    internal constructor(host: I1, host2: I2) {
        mI1 = host
        mI2 = host2
    }

    companion object {

        fun <T> create(host: T): Test where T : Test.I1, T : Test.I2 {
            return Test(host, host)
        }

    }
}

fun <T> test(host: T): Test where T : Test.I1, T : Test.I2 {
    return Test(host, host)
}

我们现在可以调用Test.create(host)test(host)来创建实例。

答案 1 :(得分:2)

展开nhaarmananswer,您可以operator overloading使Test的{​​{3}}实施invoke operator }:

class Test {

    interface I1

    interface I2

    private val mI1: I1
    private val mI2: I2

    private constructor(i1: I1, i2: I2) {
        mI1 = i1
        mI2 = i2
    }

    companion object {
        operator fun <T> invoke(host: T): Test where T : I1, T : I2 {
            return Test(host, host)
        }
    }
}

然后,您可以使用所需的调用语法创建Test对象:

Test(object : Test.I1, Test.I2 {})