使用不可变属性更改Kotlin中对象的状态

使用不可变属性更改Kotlin中对象的状态,kotlin,Kotlin,在Kotlin中,我们有不可变属性的概念 我曾经听说在函数式编程中,状态不应该改变。我一直在域模型的上下文中考虑这一点 假设我们有一个Person类(请不要介意这个非常愚蠢和不现实的例子) 所有属性都是不可变的,这很好 现在有人来了,要求替换名字。所以我创建了一个函数来实现这一点 fun replaceFirstName(person: Person, newFirstName: String): Person { return Person(newFirstName, person.l

在Kotlin中,我们有不可变属性的概念

我曾经听说在函数式编程中,状态不应该改变。我一直在域模型的上下文中考虑这一点

假设我们有一个
Person
类(请不要介意这个非常愚蠢和不现实的例子)

所有属性都是不可变的,这很好

现在有人来了,要求替换名字。所以我创建了一个函数来实现这一点

fun replaceFirstName(person: Person, newFirstName: String): Person {
    return Person(newFirstName, person.lastName, person.age)
}
在我看来这真的很难看。在这种情况下,只有3个属性,其中一个应该更换。但您可能可以想象在更大的域类中这会是什么样子

简单的方法是用
var
替换
val
,但是不变性的全部意图就消失了

我正在寻找类似这样的东西(由于没有复制函数,它确实会抛出一个错误):

在Kotlin中有没有一种简洁的方法可以做到这一点?

Kotlin有一个概念,它具有您需要的
复制功能。因此,如果您将您的类声明为:

data class Person(val firstName:String, val lastName:String, val age:Int)

您将能够使用此功能。此外,它还将为您生成
equals()/hashCode/toString()

如果您感兴趣,也可以使用

对于一个简单的情况来说,这可能不是必需的,但是当您有非常深的对象,只需要更改一个属性时,它可能非常有用:

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) } }
)
以及:

以及:


我很感兴趣。谢谢分享。
data class Person(val firstName:String, val lastName:String, val age:Int)
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)