kotlin - 在 Kotlin 中为不可变数据类重用映射代码
问题描述
更新:从评论中添加了一些澄清
我想对copy()
immutable 的主构造函数和方法使用相同的“映射”代码data class
。我怎么能做到这一点而不先创建一个空对象,然后copy()
在它上面使用?
现在的问题是,如果我添加一个具有默认值的新属性,Employee
并且EmployeeForm
很容易只将它添加到两个映射函数之一中而忘记另一个(toEmployeeNotReusable
/ copyEmployee
)。
这些是我想映射的数据类:
@Entity
data class Employee(
val firstName: String,
val lastName: String,
val jobType: Int,
@OneToMany(mappedBy = "employee", cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
private val _absences: MutableSet<Absence> = mutableSetOf(),
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0 // prevents @Joffrey's answer from working
) {
init {
_absences.forEach { it.employee = this }
}
val absences get() = _absences.toSet()
fun addAbsence(newAbsence: Absence) {
newAbsence.employee = this
_absences += newAbsence
}
@Entity
@Table(name = "absence")
data class Absence(
// ... omitted fields
) {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "employee_id")
lateinit var employee: Employee
}
}
data class EmployeeForm(
var firstName: String = "",
var lastName: String = "",
var jobType: Int = 0
) {
// not reusable
fun toEmployeeNotReusable(): Employee {
return Employee(firstName, lastName, jobType)
}
// works but hacky
fun toEmployee(): Employee {
return copyEmployee(Employee("", "", 0))
}
fun copyEmployee(employee: Employee): Employee {
return employee.copy(
firstName = firstName,
lastName = lastName,
jobType = jobType
)
}
}
虽然可变性很好,但就我而言,我很想知道这怎么可能。
解决方案
您应该能够使用反射来做到这一点:检查Employee
and中的属性列表,EmployeeForm
通过匹配的名称调用构造函数(callBy
用于处理默认参数)。当然,缺点是如果缺少任何属性,您将不会收到编译时错误(但在这种情况下,任何测试都可能会失败并告诉您问题所在)。
近似且未经测试(不要忘记添加kotlin-reflect
依赖项):
inline fun <reified T> copy(x: Any): T {
val construct = T::class.primaryConstructor
val props = x::class.memberProperties.associate {
// assumes all properties on x are valid params for the constructor
Pair(construct.findParameterByName(it.name)!!,
it.call(x))
}
return construct.callBy(props)
}
// in EmployeeForm
fun toEmployee() = copy<Employee>(this)
您可以制作一个使用 Scala 宏在编译时检查的等效项,但我认为这在 Kotlin 中是不可能的。
推荐阅读
- python - 哪个类在 Django REST 中调用序列化程序类
- python - 我可以在 python 脚本中使用 FFMPEG 将列表中的 mp4 文件合并到一个文件中吗
- java - 从 Kotlin 中的 deeplink Url 中提取 QueryParameters
- c++ - 当我为 long long 变量分配更大的数字时,为什么变量为 0?
- c++ - 如何配置 CodeLite IDE 以使用 C++ 和 SFML 库?(Windows/Linux) 配置完整解决方案
- javascript - 是否有任何处理程序来旋转对象?
- wordpress - 如何使叠加层出现在 Elementor 中的图像上方?有关更多详细信息,请参阅快照
- java - 如何用java替换文本文件中的特定字符串?
- javascript - 如何运行 JS 文件(使用 JSON)?
- flutter - 如何在 Flutter 中进行服务