我可以在scala中使用协方差传递不同的表单数据类型吗?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我可以在scala中使用协方差传递不同的表单数据类型吗?相关的知识,希望对你有一定的参考价值。
就像documentation for covariance说的那样:
对于某些类List [+ A],使A变量意味着对于两种类型A和B,其中A是B的子类型,则List [A]是List [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
的每个子类型编写此类方法。欢迎任何帮助/启发!
为了澄清我想要能够做到这一点的理由 - 这是为了避免为每个表单编写重复的代码行。因此,如果我有多个表单,我宁愿在控制器中有一个方法来绑定请求中的数据,例如
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存在的原因之一。
不,我不认为您提到的链接引用可以在您的示例中使用。为了工作,Form
类本身应该在T
Form[+T]
中被声明为协变,他们不能这样做,因为它用于两个方向的转换。你仍然可以做你喜欢的事情
def acceptAnySubTypeOfSuperCovariance[T:<SuperCovariance](myForm: Form[T])(implicit request: Request[AnyContent]): Result =
但是这段代码让我很奇怪:你真的想通过Form[some subclass of SuperCovariance]
吗?你的acceptAnySubTypeOfSuperCovariance
真正做了什么你想要这样做?通常,从请求绑定数据并获取对象然后传递它更有意义。这将在不需要泛型的情况下工作。
以上是关于我可以在scala中使用协方差传递不同的表单数据类型吗?的主要内容,如果未能解决你的问题,请参考以下文章