scala - 模式匹配 - 值不是绑定变量的成员
问题描述
我正在通过 Scala (ver. 2.13.2
) 工作,在这里我定义了一个带有 trait 的简单链表ListSeq
。另外,我想重写一个toString
漂亮打印的方法。为此,我决定使用模式匹配。assert
在案例中可以看到预期的结果
sealed trait ListSeq {
override def toString: String = s"[$elemSequence]"
private def elemSequence: String = {
this match {
case ListPair(hd, tl @ ListPair(_, _)) => s"$hd, ${tl.elemSequence}"
case ListPair(hd, EmptyList) => s"$hd"
case EmptyList => ""
}
}
}
case class ListPair(head: Int, tail: ListSeq) extends ListSeq
case object EmptyList extends ListSeq
object ListSeqExample extends App {
val seq1 = ListPair(1, ListPair(2, ListPair(3, EmptyList)))
val seq2 = EmptyList
assert(seq1.toString == "[1, 2, 3]")
assert(seq2.toString == "[]")
}
问题
此代码无法编译,错误是:
value elemSequence is not a member of ListPair
case ListPair(hd, tl @ ListPair(_, _)) => s"$hd, ${tl.elemSequence}"
我不清楚为什么会出现此错误。据我所知,Scala 可以匹配嵌套字段并将字段绑定到变量 - 就像在case ListPair(hd, tl @ ListPair(_, _))
. 但是从错误信息来看,似乎无法猜测绑定对象的类型(ListPair
)
奇怪的行为
另一个有趣的事情是 - 如果我ListSeq
以以下方式重新定义 - 通过删除该elemSequence
方法,并且所有字符串创建都在其中完成toString
-没有错误:
sealed trait ListSeq {
override def toString: String = this match {
case ListPair(hd, tl @ ListPair(_, _)) => s"$hd, ${tl.toString}"
case ListPair(hd, EmptyList) => s"$hd"
case EmptyList => ""
}
}
我知道结果toString
会略有不同(没有大括号),但这不是这里的重点。
问题
为什么在一种情况下会出错,而在另一种情况下却可以愉快地编译?
解决方案
它返回一个错误,因为它是在中定义elemSequence
的方法,所以它在 中不可见。private
ListSeq
ListPair
一种解决方案可能是将可见性更改为protected
(并添加修饰符 final 以便子类无法override
使用该方法):
sealed trait ListSeq {
override def toString: String = s"[$elemSequence]"
final protected def elemSequence: String = {
this match {
case ListPair(hd, tl @ ListPair(_, _)) => s"$hd, ${tl.elemSequence}"
case ListPair(hd, EmptyList) => s"$hd"
case EmptyList => ""
}
}
}
case class ListPair(head: Int, tail: ListSeq) extends ListSeq
case object EmptyList extends ListSeq
object ListSeqExample extends App {
val seq1 = ListPair(1, ListPair(2, ListPair(3, EmptyList)))
val seq2 = EmptyList
assert(seq1.toString == "[1, 2, 3]")
assert(seq2.toString == "[]")
}
推荐阅读
- c++ - getline(ifstream, line) 的返回字符串为空
- html - 如何将溢出的列表项修复到其他列
- javascript - Mongoose save() 和 find() 没有运行
- swift - 排除 Swift 包中的文件
- python - 值错误:标签的长度必须为“x”python 3
- python - 如何在硒中选择没有选项标签的弹出菜单选项?
- pyspark - 获取上个月的值
- math - 计算一个正方形在旋转 45 度后需要缩小多少
- java - 此版本不符合 Google Play 64 位要求。本机 Java 应用程序的所有 .so 都已存在
- c - If else C 中的错误