出于示例目的,假设您有以下内容:
import play.api.data._
import play.api.data.Forms._
case class TestDomainClass(text: String, number: Int, date: DateTime, long: Long, boolean: Boolean)
val testForm = Form(
mapping(
"textField" -> text,
"numberField" -> number,
"dateField" -> jodaDate,
"longField" -> longNumber,
"booleanField" -> boolean
)(TestDomainClass.apply)(TestDomainClass.unapply)
)
我的目标是在每个字段的参数类型上进行模式匹配。例如:对于textField
,参数类型为String
,而dateField
则为org.joda.time.DateTime
。
def typeOfMappingUsingTypeTag[T: TypeTag](m: Mapping[T]) = typeOf[T] match {
case t if t =:= typeOf[String] => println("type is String")
case t if t =:= typeOf[Int] => println("type is Int")
case t if t =:= typeOf[org.joda.time.DateTime] => println("type is DateTime")
case t if t =:= typeOf[Long] => println("type is Long")
case t if t =:= typeOf[Boolean] => println("type is boolean")
case _ => println("type is something else")
}
for(m <- testForm.mapping.mappings if m.key.nonEmpty) {
print(m.key)
typeOfMappingUsingTypeTag(m)
}
使用以下输出:
textFieldtype is something else
numberFieldtype is something else
dateFieldtype is something else
longFieldtype is something else
booleanFieldtype is something else
所以没有运气,这在某种程度上是预期的,因为在source the Mapping中没有与TypeTag绑定的上下文。
def typeOfMappingUsingPatternMatch[T](m: Mapping[T]) = m match {
case text => println("type is String")
case number => println("type is Int")
case jodaTime => println("type is DateTime")
case longNumber => println("type is Long")
case boolean => println("type is Boolean")
case _ => println("type is something else")
}
for(m <- testForm.mapping.mappings if m.key.nonEmpty) {
print(m.key)
typeOfMappingUsingPatternMatch(m)
}
使用以下输出:
textFieldtype is String
numberFieldtype is String
dateFieldtype is String
longFieldtype is String
booleanFieldtype is String
以下编译警告:
[warn] /aFolder/aProject/app/controllers/IPBlocks.scala:58: patterns after a variable pattern cannot match (SLS 8.1.1)
[warn] case text => println("type is String")
[warn] ^
[warn] /aFolder/aProject/app/controllers/IPBlocks.scala:59: unreachable code due to variable pattern 'text' on line 58
[warn] case number => println("type is Int")
[warn] ^
与其余案件的警告相同。
如果我改变了案例的顺序,无论哪种情况最终成为第一个,都是被打印的那个(例如,如果案例布尔是第一种情况,那么每个案例的输出将是is Boolean
字段)
考虑输出:
val t = text
println("t == number " + (t == number))
println("t == text " + (t == text))
println("t eq number " + (t eq number))
println("t eq text " + (t eq text))
是
t == number true
t == text true
t eq number false
t eq text true
使用ifs和eq似乎可以解决问题,所以我尝试过:
def typeOfMappingUsingIfAndEq[T](m: Mapping[T]) = {
if (m eq text) {
println("type is String")
} else if (m eq number) {
println("type is Int")
} else if (m eq jodaDate) {
println("type is DateTime")
} else if (m eq longNumber) {
println("type is Long")
} else if (m eq boolean) {
println("type is Boolean")
} else {
println("type is something else")
}
}
for(m <- testeForm.mapping.mappings if m.key.nonEmpty) {
print(m.key)
typeOfMappingUsingIfAndEq(m)
}
使用以下输出
textFieldtype is something else
numberFieldtype is something else
dateFieldtype is something else
longFieldtype is something else
booleanFieldtype is something else
那么,问题是否有解决方案?如果是,那是什么? 另外,为什么地狱不能解决第三种解决方案呢?
答案 0 :(得分:0)
我不确定我是否完全理解你的目标,但是如果你想根据对象类型做事,你可以用这种方式匹配模式:
value match {
case stringValue : String => // value es a String! You can use the stringValue variable which's type is String but reference the same object
case intValue : Int => // value is an Int. Do stuff.
...
case _ => // any other case
}
关于你的第三个实现,请注意使用eq。 Eq检查身份,这与平等不同。 (您可以查看this post了解更多信息)。另外,由于您的代码脱离了上下文,我不确定这些变量是如何定义的,但是,例如,如果我们采用这些行:
def typeOfMappingUsingIfAndEq[T](m: Mapping[T]) = {
if (m eq text) {
...
如果文字变量的类型为字符串(因为它位于 TestDomainClass ),则无法进行等于/等于m,其类型为 Mapping [T] )。
希望这有帮助!
祝你好运!