我正在爲我的web應用程序中的操作構建一個框架。基本思想是它可以離線工作,所以我需要一種方式來傳遞發生的操作,然後可以重新合併,重播等等。 ActionMeta是啓用此行爲的類,並且表示單個操作,類型S是操作的主題類型。以下是構成它的實際參數。斯卡拉,將值傳遞給任何集合
case class ActionMeta[S](
val timestamp: Instant,
val syncKey: SyncKey,
val action: Action[S],
val subjectId: UUID,
val subjectClientId: UUID,
val originMeta: JsValue,
val actionArgs: JsValue,
val status: ActionStatus,
val syncStatus: ActionSyncStatus,
val subActions: List[(Option[Any], ActionMeta[Any])]
) {
}
這和它的行爲工作,我的規格爲單行動和具有相同主題的動作堆棧,但現在我需要解決的最後一行,也就是子行動。關鍵問題是子行動往往會涉及不同的主題。操作本身被繼承的對象從這些性狀:
trait Action[S] {
val registryKey: String
ActionRegistry.register(registryKey, this)
def getSubjectIds(subject: S): (UUID, UUID)
def pullOriginMeta(subject: S): JsValue
def getSubjectRepresentation(id: UUID, clientId: UUID): S
def saveSubjectRepresentation(subject: S): S
def merge(args: JsValue, newArgs: JsValue): Option[JsValue]
def deleteSubjectRepresentation(id: UUID, clientId: UUID): Boolean
}
trait CreationAction[S] extends Action[S] {
def apply(actionArgs: JsValue = JsNull): (S, ActionMeta[S]) = {
val (res, updatedActionArgs) = this.forwards(actionArgs)
val (sid, scid) = this.getSubjectIds(res)
val actionMeta = new ActionMeta[S](
DateTime.now.toInstant, new SyncKey(), this, sid, scid,
JsNull, updatedActionArgs, Done, LocalAction, this.runSubActions(actionArgs)
)
(res, actionMeta)
}
def forwards(args: JsValue): (S, JsValue)
def backwards(subject: S, args: JsValue): JsValue
def runSubActions(forwardArgs: JsValue): List[(Option[Any], ActionMeta[Any])] = {
List()
}
}
也有TransformAction [S]和DeletionAction [S]的性狀,這是類似的,但具有不同類型的簽名forwards
/backwards
,併爲不同的邏輯apply
。
object TestSideActionCreate extends {val registryKey = "actions:testSideCreate"}
with TestSideActionBase with CreationAction[TestSide] {
// omitted method bodies, not necessary to problem
def forwards(args: JsValue): (TestSide, JsValue) = ???
def backwards(subject: TestSide, args: JsValue): JsValue = ???
def merge(args: JsValue, newArgs: JsValue): Option[JsValue] = ???
override def runSubActions(args: JsValue): List[(Option[Any], ActionMeta[Any])] = {
List(
TestActionCreate(
Json.obj("id" -> UUID.randomUUID.toString)
).asInstanceOf[(Option[Any], ActionMeta[Any])]
)
}
}
基本上我的問題是,runSubActions
因爲它是笨重的。這個方法可以工作,我可以像我期望的那樣使用完整的類型來訪問生成的子動作,但是,這仍然是我要做的很多我的最終實現,我的API,所以我不想如果我可以幫助它,則迫使編譯器通過使用asInstanceOf來通過一系列不同類型的子動作。
有沒有更好的方式來表達這種類型系統?我需要能夠接受List[Option[Any], ActionMeta[Any]]
中的任何內容,因爲我不想把我的雙手綁在一起:只要它實現了ActionMeta[S]
並具有相應的Action[S]
,我可以依靠它來表現可預測性。
乾杯。
包裝聽起來更符合我想要做的事情。想想在繼續之前,我會再想一想如何去做。 – MalucoMarinero