模式匹配 - 值不是绑定变量的成员
Pattern matching - value is not a member on a bound variable
我正在学习 Scala(版本 2.13.2
),在这里我定义了一个具有特征 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
的结果会略有不同(没有大括号),但这不是这里的重点
问题
为什么在一种情况下出现错误,而在另一种情况下却可以顺利编译?
是私有方法。这些不被子类继承或访问(在 Scala 或 Java 中)。
将其更改为受保护或 public 或包私有将解决此问题。
它 returns 一个错误,因为 elemSequence
是 ListSeq
中定义的 private
方法,所以它在 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 == "[]")
}
我正在学习 Scala(版本 2.13.2
),在这里我定义了一个具有特征 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
的结果会略有不同(没有大括号),但这不是这里的重点
问题
为什么在一种情况下出现错误,而在另一种情况下却可以顺利编译?
是私有方法。这些不被子类继承或访问(在 Scala 或 Java 中)。
将其更改为受保护或 public 或包私有将解决此问题。
它 returns 一个错误,因为 elemSequence
是 ListSeq
中定义的 private
方法,所以它在 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 == "[]")
}