看起来像构造

比如:

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 有两条约定叠在一起:

  1. 接口名可以当 companion 用,默认对象叫 Companion
  2. a(i) 翻译成 a.invoke(i),前提是 invoke 标了 operator
companion invoke 的两层语法糖

所以源码里那一行,语义是:

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 operatorcompanion objects。同类约定见 Kotlin运算符重载operator关键字


相关笔记