Kotlin:乐趣与价值

Kotlin: fun vs val

Kotlin 支持计算属性,但我不确定何时使用它们。

假设我有一个 class:

class Car(val color: String)

并且有这个功能returns true如果车是白色的:

fun isWhite(car: Car): Boolean {
  return car.color == "WHITE"
}

现在我希望这个函数成为一个成员函数(一个方法);这看起来像这样:

class Car(val color: String) {
  fun isWhite(): Boolean = color == "WHITE"
}

但它也可以是这样的:

class Car(val color: String) {
  val isWhite: Boolean get() = color == "WHITE"
}

那么,哪个更好呢?

个人喜好。

我的观点是,如果您不需要传递任何东西,则将其创建为 属性。

但是如果你需要给它传递更多的信息,那就必须是一个函数了!

官方 Kotlin Coding Conventions 在部分 函数与属性 中定义如下:

In some cases functions with no arguments might be interchangeable with read-only properties. Although the semantics are similar, there are some stylistic conventions on when to prefer one to another.

Prefer a property over a function when the underlying algorithm:

  • does not throw
  • is cheap to calculate (or caсhed on the first run)
  • returns the same result over invocations if the object state hasn't changed

所以,我会在上面的例子中使用 val 作为 isWhite,因为它不会抛出,字符串比较计算成本低,color Car 无法更改,因为 Car.color 本身定义为 val.

编译差异

请注意,get() 块的 JVM 字节码将被编译为与函数所具有的代码完全相同的代码。因此,对于编译的字节码和 there is no performance difference.

这两种方法是相同的

要添加其他答案,这些答案来自 Java to Kotlin 一书,第 11 章 属性方法

示例 1

假设我们要将 age 添加到 class:

data class Person(val dateOfBirth: LocalDate)

我们可以根据 dateOfBirth 属性 轻松计算年龄(忽略时区)。但这不仅仅取决于 属性;这也取决于我们何时调用它。
尽管不太可能,fred.age == fred.age 可以 return false.

年龄是一个动作;它的结果取决于它何时被调用。特性 应该是计算,永恒的并且只依赖于他们的输入,在这种情况下是dateOfBirth 属性.
因此,age() 应该是一个函数,而不是 属性:

data class Person(val dateOfBirth: LocalDate) {
    fun age() = Period.between(dateOfBirth, LocalDate.now()).years
}

示例 2

如果我们想要对象所有其他属性的加密散列怎么办? 这是一个 计算 (对于不可变对象),但如果计算成本很高,它应该是一个方法 hash() 而不是 属性 hash .我们甚至可能想在其名称中暗示该方法的成本:

data class PersonWithProperties(
    val givenName: String,
    val familyName: String,
    val dateOfBirth: LocalDate
) {
    fun computeHash(): ByteArray =
        someSlowHashOf(givenName, familyName, dateOfBirth.toString())
}