普通表达式和单一表达式函数定义之间的差异



>假设一个Android项目,其中有两个按钮的XML:

<layout>
<data>
<variable name="viewModel" type="com.package.package.UploadPhotoViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
android:padding="10dp">
<com.zoosk.zoosk.ui.widgets.ProgressButton
android:id="@+id/progressButtonChooseFromLibrary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.choosePhotoText}"
android:onClick="@{viewModel::choosePhotoButtonClick}"
android:visibility="@{viewModel.choosePhotoVisibility}" />
<com.zoosk.zoosk.ui.widgets.ProgressButton
android:id="@+id/progressButtonTakePhoto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.takePhotoText}"
android:onClick="@{viewModel::takePhotoButtonClick}"
android:visibility="@{viewModel.takePhotoVisibility}" />
</LinearLayout>
</layout>

以及随附的视图模型:

class UploadPhotoViewModel(resources: Resources) {
var onChoosePhotoButtonClicked: ((View) -> Unit)? = null
var onTakePhotoButtonClicked: ((View) -> Unit)? = null
fun choosePhotoButtonClick(v: View) {
onChoosePhotoButtonClicked?.invoke(v)
}
fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v)
}

特别注意到choosePhotoButtonClicktakePhotoButtonClick的申报方式之间的差异。

在构建这个项目时,Android的数据绑定将正常工作choosePhotoButtonClick,但抛出一个错误与takePhotoButtonClick,说没有方法与预期的引用签名匹配。 假设这些方法在后台以相同的方式创建,这不应该发生,唉,一定有一些区别。

这两种声明语法到底有什么区别? 官方的 Kotlin 文档没有提到任何功能,只是说它可以作为声明该方法的另一种方式。

如果你使用大括号而不指定返回类型, 你的函数隐式重新调整Unit(这是 Kotlin forvoid(,所以你的方法:

fun choosePhotoButtonClick(v: View) {
onChoosePhotoButtonClicked?.invoke(v)
}

具有以下签名:

fun choosePhotoButtonClick(v: View) : Unit

(IDE 将提示返回类型"Unit"是多余的,可以省略(。

但是,使用等号来速记函数会推断右侧表达式的返回类型,例如:

fun itemCount() = items.size

将推断Int的返回类型,所以它的签名是:

fun itemCount() : Int

在您的情况下:

fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v)

函数可以在onTakePhotoButtonClicked为 null 时返回null或返回该方法的值 (Unit(,这意味着您的takePhotoButtonClick签名是:

fun takePhotoButtonClick(v: View) : Unit?

(OP(直接解决问题:

fun takePhotoButtonClick(v: View) = onTakePhotoButtonClicked?.invoke(v) ?: Unit

可以认为比大括号版本可读性低,但这意味着返回类型为 Unit 而不是 Unit?,并且将被数据绑定正确拾取。

最新更新