【发布时间】:2018-06-05 13:03:13
【问题描述】:
与documentation for covariance 声明的方式相同:
对于某些类 List[+A],使 A 协变意味着对于两种类型 A 和 B 其中 A 是 B 的子类型,则 List[A] 是 列表[B]
这也可以应用于Form(如 scala 形式)?我在传递各种类型的表格时遇到问题。这是我正在做的一个示例:
abstract class SuperCovariance
case class TestCovariance1(id: Option[Int], name: String, another: String) extends SuperCovariance
case class TestCovariance2(id: Option[Int], differentName: String, other: String) extends SuperCovariance
object Tc1Form {
val form = Form(
mapping(
"_id" -> optional(number),
"name" -> nonEmptyText,
"another" -> nonEmptyText
)(TestCovariance1.apply)(TestCovariance1.unapply)
)
}
object Tc2Form {
val form = Form(
mapping(
"_id" -> optional(number),
"differentName" -> nonEmptyText,
"other" -> nonEmptyText
)(TestCovariance2.apply)(TestCovariance2.unapply)
)
}
如果其中一种形式可以作为参数传递给我认为可以这样做的方法:
def acceptAnySubTypeOfSuperCovariance(myForm: Form[SuperCovariance])(implicit request: Request[AnyContent]): Result = {
Ok(views.html.myTemplate(myForm))
}
调用此方法并传递Form[TestCovariance1] 类型会导致错误,这导致我在理解以及如何避免为SuperCovariance 的每个子类型编写此类方法方面遇到问题。欢迎任何帮助/启发!
澄清我希望能够做到这一点的原因 - 这是为了避免为每个表单编写重复的代码行。因此,如果我有多种形式,我希望在 controller 中使用一种方法来绑定来自请求的数据,例如
def updateDoc(collectionName: String, oId: Option[BSONObjectID]) = Action.async { implicit request: Request[AnyContent] =>
MyModel.form.bindFromRequest.fold(
errorForm => Future.successful(Ok(views.html.errorTemplate(errorForm, MyModel)),
data => {
val updatedDoc = ?? // map data to model here, e.g. TestCovariance1(None, data.name, data.another)
// calls a method
updateMultipleFields[MyModel](collectionName, updatedDoc, oId).map(x =>
Redirect(routes.DatabaseC.editIndex(collName, oId.get))
)
}
)
}
// generic method to update fields in collection (Mongo database)
def updateMultipleFields[T](collectionName: String, model: T, id: Option[BSONObjectID])(implicit writes: Writer[T]): Future[Result] = {
val idSelector = Json.obj("_id" -> id)
getCollection(collectionName).flatMap(collection =>
collection.update(idSelector, Json.obj("$set" -> model)).map {
lastError =>
Created("fields updated")
}
)
}
我认为 MVC 结构会很灵活,允许我以正确(且安全)的方式设置数据处理;我可以通过创建新模型(表单和模型)来简单地添加数据。如果我不能;它不会阻止应用程序的功能,但似乎重复这些类似 样板 的代码是 Scala 存在的原因之一。
【问题讨论】:
-
抛出的错误是什么?我认为在这种情况下你不需要强制协方差。
-
@nicodp 错误是 - *类型不匹配,预期:Form[SuperCovariance],预期:Form[TestCovariance1] *
-
抱歉 - 错字:*类型不匹配,预期:Form[SuperCovariance],实际:Form[TestCovariance1] *
标签: forms scala types playframework covariance