看起来像构造
比如:
CardFactory(item, context)?.let { cardView ->
cardView.bind(item)
}CardFactory 是 interface,没有构造函数,也没有人 implements 它。这行能编译,不是因为 new 了一个接口。
真正写了方法的地方在 companion 里:
interface CardFactory {
companion object {
operator fun invoke(
item: CardItem,
context: Context
): CardView? {
return when (item) {
is CouponItem -> CouponCardView(context)
is ImageItem -> ImageCardView(context)
else -> null
}
}
}
}CouponCardView(context) 才是构造,new 出一个 View。CardFactory(...) 只是按类型选工厂,未知类型返回 null,所以后面才接 ?.let。
编译器补了两层
Kotlin 有两条约定叠在一起:
- 接口名可以当 companion 用,默认对象叫
Companion。 a(i)翻译成a.invoke(i),前提是invoke标了operator。
所以源码里那一行,语义是:
CardFactory.Companion.invoke(item, context)下面四行是同一次调用。第一行最省,也最容易看成构造:
CardFactory(item, context)
CardFactory.invoke(item, context)
CardFactory.Companion(item, context)
CardFactory.Companion.invoke(item, context)少写 operator,或把名字改成 create,类型名后面的括号都会编译失败。create() 只能显式写方法名。
官方依据:invoke operator、companion objects。同类约定见 Kotlin运算符重载、operator关键字。
评论