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())
}
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())
}