在Kotlin,我们有这种不可变属性的概念。
我曾经听说过在功能编程中,状态不应该改变。我一直在域模型的背景下思考这个问题。
假设我们有一个Person
课程(请不要介意这个非常愚蠢和不切实际的例子)。
class Person(val firstName: String, val lastName: String, val age: Int)
Everything属性是不可变的,这很好。
现在有人出现并要求更换名字。所以我创建了一个可以做到这一点的函数。
fun replaceFirstName(person: Person, newFirstName: String): Person {
return Person(newFirstName, person.lastName, person.age)
}
现在这看起来真的很难看我的眼睛。在这种情况下,只有3个属性,其中一个应该被替换。但你可以想象在较大的域类中它会是什么样子。
简单的做法就是将val
替换为var
,但随后不变的整个意图就消失了。
我正在寻找类似的东西(由于没有复制功能,它会抛出错误):
fun replaceName(person: Person, newFirstName: String): Person {
return person.copy { firstName = newFirstName }
}
在Kotlin有一个简洁明了的方法吗?
答案 0 :(得分:3)
Kotlin的概念为Data classes,具有您需要的copy
功能。因此,如果您将您的课程声明为:
data class Person(val firstName:String, val lastName:String, val age:Int)
您将能够使用此功能。此外,它还会为您生成equals()/hashCode/toString()
。
答案 1 :(得分:3)
如果您有兴趣,也可以使用lens执行此操作。
这可能不是一个简单的案例,但是当你有非常深的对象只需要改变一个属性时,它就会很有用:
import arrow.optics.*
data class Person(val firstName:String, val lastName:String, val age:Int)
val firstNameLens: Lens<Person, String> = Lens(
get = { person -> person.firstName },
set = { newFirstName-> { person -> person.copy(firstName = newFirstName) } }
)
然后你可以这样做:
val doe = Person("John", "Doe", 30)
firstNameLens.set(doe, "Henry")
//output: Person(firstName = "Henry", lastName = "Doe", age = 30)
和
val doe = Person("John", "Doe", 30)
firstNameLens.get(doe)
//output: "John"
和
val doe = Person("John", "Doe", 30)
firstNameLens.modify(doe, { it + "ny" })
//output: Person(firstName = "Johnny", lastName = "Doe", age = 30)