大/长案例类的模式匹配

时间:2016-08-25 08:04:11

标签: scala pattern-matching

是否有一种更具可读性和更强大(重构)的方式来匹配像这样的案例类?

实施例

案例类

非常长的案例类,包含许多“字段”。

case class Data(name: String, time: Long, ..., userId: Option[UUID] ..., orders: Int, ... ) //more fields fields more

模式匹配:变体a

作品。但是当字段位置改变时容易出错。最终会计算_

res match {
  case data@Data(_,_,_,_,_,_,Some(id),_,_,_,6,_,_) => (id, data.orders)
  case _ => ... 

} 

模式匹配:变体b

也可以。对订单变更稳定。通过更多的检查来获得真正的麻烦。还必须重复阅读该值。

res match {
  case data: Data if data.userId.isDefined && data.orders == 6 => (data.userId.get,data.orders)
  case _ => ...
} 

问题改写

有没有办法将Variant A和B结合起来以获得两种方法的好处?

2 个答案:

答案 0 :(得分:11)

您可以使用自定义提取器:

res match {
  case ExtractUserIdAndOrders(Some(id), 6) => ...
  case _ => ...
}

,其中

object ExtractUserIdAndOrders {
  def unapply(data: Data) = Some((data.userId, data.orders))
}

如果您只需要一次,您可以在方法内定义它,或者在更广泛的范围内为多个类似的匹配定义它。

答案 1 :(得分:2)

只要范围中有case class Big(foo: String, bar: String, baz: Option[String], x: Int, y: Int) object SmallerBig { def unapply(x: Big): Option[(Option[String], Int)] = Some(x.baz, x.y) } val x = Big("a", "b", Some("c"), 1, 2) x match { case Big(_, _, _, _, _) => case SmallerBig(Some(a), b) => } 方法,它从您要匹配的类型中获取参数,就可以为此定义自定义提取器,例如

Option

unapply方法的返回类型不能是get,但您返回的类型必须提供方法isDefinedClass USER { public $_user; public function userLogin($username,$password) { $statusY = "Y"; $stmt = $this->connection->prepare("SELECT * FROM tbl_users WHERE user_name=:userName LIMIT 1"); $stmt ->execute(array(":userName"=>$username)); $row = $stmt ->fetch(PDO::FETCH_ASSOC); if($stmt->rowCount() == 1) { $this->_user = $row; // Assign user details $_SESSION['userSession'] = $row['user_id']; } } public function getUser() { return $this->_user; } }