scala - 模式匹配 - 值不是绑定(bind)变量的成员

标签 scala compiler-errors pattern-matching scala-compiler

我正在使用 Scala(版本 2.13.2),在这里我定义了一个带有特征 ListSeq 的简单链表。另外,我想重写 toString 方法以实现 pretty-print 。为此,我决定使用模式匹配。在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 可以匹配嵌套字段并将字段绑定(bind)到变量 - 就像 case ListPair(hd, tl @ ListPair(_, _)) 中所做的那样。但从错误信息来看,似乎无法猜测绑定(bind)对象的类型(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 的结果会略有不同(没有大括号),但这不是这里的要点。

问题

为什么在一种情况下会出现错误,而在另一种情况下却可以顺利编译?

最佳答案

它返回错误,因为elemSequenceListSeq中定义的私有(private)方法,因此它在ListPair中不可见>.

一种解决方案可能是将可见性更改为protected(并添加修饰符final,以便子类无法覆盖该方法):

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 - 模式匹配 - 值不是绑定(bind)变量的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67344397/

相关文章:

scala - Spark java.lang.ClassCastException : scala. collection.mutable.WrappedArray$ofRef 无法转换为 java.util.ArrayList

scala - 隐式Mapper对隐式Mapped参数的奇怪影响

java - 如何解析字符串并根据java中不同定义的模式使用它?

scala - 未检测到项目中的 SLF4J : simplelogger. 属性

scala - 在Scala中使用Futures而不是并行集合有什么好处?

java - 为什么我的子类不继承其父类(super class)的私有(private)实例变量?

c - 反转数组时,出现以下错误: invalid operands to binary * (have ‘int’ and ‘int *’ ) [closed]

java - 实例和类语法

f# - 通过函数调用区分联合模式匹配

math - Haskell 浮点错误