如何在 Scala 中的案例 class 上强制执行具有特征的属性?
How to enforce properties with traits on a case class in scala?
case class CaseClassJobEvent(
jobId: String,
jobType: Option[String],
inPlanning: Option[Boolean],
teamId: String,
actorId: String,
adminActorId: Option[String],
sessionId: String,
clientSessionId: Option[String],
clientCreatedAt: Long,
seqId: Long,
isSideEffect: Option[Boolean],
opAction: String,
stepId: Option[String],
jobBaseStepId: Option[String],
fieldId: Option[String],
serverReceivedAt: Option[Long]) extends Event
具有特征:
trait Event {
var teamId: String
var actorId: String
}
产生此错误:
class CaseClassJobEvent needs to be abstract, since:
[error] it has 2 unimplemented members.
[error] /** As seen from class CaseClassJobEvent, the missing signatures are as follows.
[error] * For convenience, these are usable as stub implementations.
[error] */
[error] def actorId_=(x: String): Unit = ???
[error] def teamId_=(x: String): Unit = ???
[error] case class CaseClassJobEvent(
[error] ^
我做错了什么?我应该做什么?无论如何使用特征或继承来强制案例 class 的属性?我不想强制执行方法只是属性。
Luis Miguel Mejía Suárez 已经回答了你的问题,所以我想我会在这里添加一些东西,这样你可能会重新考虑你的 class.
的设计
不要在您的案例 class 中创建 var,而是使用案例 class 的 .copy 方法来生成具有更改字段的新对象。
因此,如果您想更改您的案例中的 teamId 或 actorId class,请执行以下操作:
val jobEvent = CaseClassJobEvent(...)
val changedJobEvent = jobEvent.copy( teamId = "somenewvalue", actorId = "somenewvalue" )
回答你原来的问题:
trait Event {
def teamId: String
def actorId: String
}
case class CaseClassJobEvent(
jobId: String,
jobType: Option[String],
inPlanning: Option[Boolean],
var teamId: String,
var actorId: String,
adminActorId: Option[String],
sessionId: String,
clientSessionId: Option[String],
clientCreatedAt: Long,
seqId: Long,
isSideEffect: Option[Boolean],
opAction: String,
stepId: Option[String],
jobBaseStepId: Option[String],
fieldId: Option[String],
serverReceivedAt: Option[Long]) extends Event
这样的设计可能就是您想要的。这对于学校项目来说很好,但你永远不会在生产中做这样的事情,尤其是当你在多线程环境中工作时。不可变值始终是线程安全的,您可以通过向 class.
添加变量来打破它
只是需要考虑的事情。
=======
我们目前正在讨论如何在不使用可变值的情况下实现 CaseClassJobEvent。这是我建议的实现。
trait Event {
def teamId: String
def actorId: String
}
case class CaseClassJobEvent(
jobId: String,
jobType: Option[String],
inPlanning: Option[Boolean],
teamId: String,
actorId: String,
adminActorId: Option[String],
sessionId: String,
clientSessionId: Option[String],
clientCreatedAt: Long,
seqId: Long,
isSideEffect: Option[Boolean],
opAction: String,
stepId: Option[String],
jobBaseStepId: Option[String],
fieldId: Option[String],
serverReceivedAt: Option[Long]) extends Event
除teamId和actorId不是vars外,一切都和你想要的解决方案一样。
如果您需要将您的案例 class 中的 teamId 和 actorId 的值更改为其他值,请执行以下操作:
def setTeamIdAndActorId(myEvent: CaseClasJobEvent, newTeamId: Option[String], newActorId: Option[String]): CaseClassJobEvent = {
val newEvent1 = if (newTeamId.isDefined) myEvent.copy(teamId = newTeamId.get) else myEvent
val newEvent2 = if (newactorId.isDefined) newEvent1.copy(actorId = newActorId.get) else newEvent1
newEvent2
}
如果这似乎是必须修改案例的一种非常冗长的方式 class,那么您是对的。我们公司目前所做的是使用 softwaremill 的 quicklens 库来修改深度嵌套的 case classes,语法更优雅。它仍然不像重新分配一个 var 那样简单,但是在多线程环境下它更正确,并且比一直调用 copy 更不冗长。但是,就您的目的而言,如果您想在不学习新库的情况下获得正确性,那么复制可能是您最好的选择。
=======
现在对话的发展方式是,提出问题的人只想得到一个输入,如果它有特定的字段,它就会做某事。这听起来像是继承的工作。
假设我有很多事件。
trait Event
我想要一个函数,它只在我的事件有 actorId 和 teamId 时才执行某些操作。
trait IdEvent {
def teamId: String
def actorId: String
} extends Event
这是我的函数,只有当我的事件是 IdEvent 时它才会执行某些操作
def processEvent(e: Event): Option[Int] = {
e match {
case event: IdEvent => someProcess(event)
case event: Event => None
}
}
其中 someProcess 有签名
def someProcess(input: IdEvent): Option[Int]
case class CaseClassJobEvent(
jobId: String,
jobType: Option[String],
inPlanning: Option[Boolean],
teamId: String,
actorId: String,
adminActorId: Option[String],
sessionId: String,
clientSessionId: Option[String],
clientCreatedAt: Long,
seqId: Long,
isSideEffect: Option[Boolean],
opAction: String,
stepId: Option[String],
jobBaseStepId: Option[String],
fieldId: Option[String],
serverReceivedAt: Option[Long]) extends Event
具有特征:
trait Event {
var teamId: String
var actorId: String
}
产生此错误:
class CaseClassJobEvent needs to be abstract, since:
[error] it has 2 unimplemented members.
[error] /** As seen from class CaseClassJobEvent, the missing signatures are as follows.
[error] * For convenience, these are usable as stub implementations.
[error] */
[error] def actorId_=(x: String): Unit = ???
[error] def teamId_=(x: String): Unit = ???
[error] case class CaseClassJobEvent(
[error] ^
我做错了什么?我应该做什么?无论如何使用特征或继承来强制案例 class 的属性?我不想强制执行方法只是属性。
Luis Miguel Mejía Suárez 已经回答了你的问题,所以我想我会在这里添加一些东西,这样你可能会重新考虑你的 class.
的设计不要在您的案例 class 中创建 var,而是使用案例 class 的 .copy 方法来生成具有更改字段的新对象。
因此,如果您想更改您的案例中的 teamId 或 actorId class,请执行以下操作:
val jobEvent = CaseClassJobEvent(...)
val changedJobEvent = jobEvent.copy( teamId = "somenewvalue", actorId = "somenewvalue" )
回答你原来的问题:
trait Event {
def teamId: String
def actorId: String
}
case class CaseClassJobEvent(
jobId: String,
jobType: Option[String],
inPlanning: Option[Boolean],
var teamId: String,
var actorId: String,
adminActorId: Option[String],
sessionId: String,
clientSessionId: Option[String],
clientCreatedAt: Long,
seqId: Long,
isSideEffect: Option[Boolean],
opAction: String,
stepId: Option[String],
jobBaseStepId: Option[String],
fieldId: Option[String],
serverReceivedAt: Option[Long]) extends Event
这样的设计可能就是您想要的。这对于学校项目来说很好,但你永远不会在生产中做这样的事情,尤其是当你在多线程环境中工作时。不可变值始终是线程安全的,您可以通过向 class.
添加变量来打破它只是需要考虑的事情。
=======
我们目前正在讨论如何在不使用可变值的情况下实现 CaseClassJobEvent。这是我建议的实现。
trait Event {
def teamId: String
def actorId: String
}
case class CaseClassJobEvent(
jobId: String,
jobType: Option[String],
inPlanning: Option[Boolean],
teamId: String,
actorId: String,
adminActorId: Option[String],
sessionId: String,
clientSessionId: Option[String],
clientCreatedAt: Long,
seqId: Long,
isSideEffect: Option[Boolean],
opAction: String,
stepId: Option[String],
jobBaseStepId: Option[String],
fieldId: Option[String],
serverReceivedAt: Option[Long]) extends Event
除teamId和actorId不是vars外,一切都和你想要的解决方案一样。
如果您需要将您的案例 class 中的 teamId 和 actorId 的值更改为其他值,请执行以下操作:
def setTeamIdAndActorId(myEvent: CaseClasJobEvent, newTeamId: Option[String], newActorId: Option[String]): CaseClassJobEvent = {
val newEvent1 = if (newTeamId.isDefined) myEvent.copy(teamId = newTeamId.get) else myEvent
val newEvent2 = if (newactorId.isDefined) newEvent1.copy(actorId = newActorId.get) else newEvent1
newEvent2
}
如果这似乎是必须修改案例的一种非常冗长的方式 class,那么您是对的。我们公司目前所做的是使用 softwaremill 的 quicklens 库来修改深度嵌套的 case classes,语法更优雅。它仍然不像重新分配一个 var 那样简单,但是在多线程环境下它更正确,并且比一直调用 copy 更不冗长。但是,就您的目的而言,如果您想在不学习新库的情况下获得正确性,那么复制可能是您最好的选择。
=======
现在对话的发展方式是,提出问题的人只想得到一个输入,如果它有特定的字段,它就会做某事。这听起来像是继承的工作。
假设我有很多事件。
trait Event
我想要一个函数,它只在我的事件有 actorId 和 teamId 时才执行某些操作。
trait IdEvent {
def teamId: String
def actorId: String
} extends Event
这是我的函数,只有当我的事件是 IdEvent 时它才会执行某些操作
def processEvent(e: Event): Option[Int] = {
e match {
case event: IdEvent => someProcess(event)
case event: Event => None
}
}
其中 someProcess 有签名
def someProcess(input: IdEvent): Option[Int]