我有一些object
像这样:
interface Maker<T : Thing>
interface Thing
我希望Thing
保留对其Maker
的引用,但我不知道如何:
interface Thing {
val maker: Maker<this::class> // ??
}
这样我可以有类似的东西:
class BallMaker : Maker<Ball>
object Ball : Thing {
override val maker = BallMaker
}
我该如何实现?
答案 0 :(得分:2)
从Thing
的角度来看,其制造商必须简单地定义为Maker<*>
,这意味着任何类型的制造商。
您可以使用子类参数化Thing
。
interface Maker<T : Thing<T>> {
}
interface Thing<T : Thing<T>> {
val maker: Maker<T>
}
class Ball : Thing<Ball> {
override val maker: Maker<Ball>
}
答案 1 :(得分:1)
如果您像这样定义Maker
界面:
interface Maker<out T : Thing>
fun make(): T
}
然后您的Thing
界面可以定义为:
interface Thing {
val maker: Maker<Thing>
}
由于使用out
,可以将实现定义为:
class BallMaker : Maker<Ball> {
override fun make(): Ball = TODO("not implemented")
}
class Ball : Thing {
override val maker = BallMaker()
}
此处,maker
属性的类型为BallMaker
。您还可以使用:
override val maker: Maker<Ball> = BallMaker()
如果您希望公开接口类型而不是实现。
有关Kotlin中泛型的更多信息,请参见Generics: in, out, where - Kotlin Programming Language。关于使用out
的重要一件事是:
一般规则是:当将类
T
的类型参数C
声明为 out 时,它只能出现在 out 中-在C
的成员中排名,但作为回报,C<Base>
可以安全地成为C<Derived>
的超类型。
换句话说,如果使用out
定义了通用参数,则只能将其用作返回类型,而不能用作参数类型。 in
则相反。
当然,如果您的Maker
接口只有一种方法,则您可能需要考虑使用函数类型。
interface Thing {
val maker: () -> Thing
}
这仍然允许您执行以下操作:
class Ball : Thing {
// type can be inferred to "() -> Ball" instead in this case
override val maker: () -> Ball = { Ball() }
}
如果要命名函数类型,请使用type alias。