代码之家  ›  专栏  ›  技术社区  ›  Synesso

密封类匹配的非详尽警告

  •  0
  • Synesso  · 技术社区  · 6 年前

    鉴于

    sealed class UnionKey private (val i: Int) {
      def encode(stream: XdrDataOutputStream) = stream.writeInt(i)
    }
    
    object UnionKey {
      def decode(stream: XdrDataInputStream): UnionKey = stream.readInt() match {
        case 1 => ONE
        case 2 => TWO
        case 3 => OFFER
        case i => throw new IllegalArgumentException(s"UnionKey value $i is invalid")
      }
    
      case object ONE extends UnionKey(1)
      case object TWO extends UnionKey(2)
      case object OFFER extends UnionKey(3)
    }
    

    编译时,我会得到一个非详尽的匹配警告:

    object MyUnion {
      def decode(stream: XdrDataInputStream): MyUnion = UnionKey.decode(stream) match {
        case UnionKey.ONE => MyUnionOne(stream.readInt)
        case UnionKey.TWO => MyUnionTwo(stream.readInt, Foo.decode(stream))
        case UnionKey.OFFER => MyUnionOffer
      }
    }
    

    警告:

    myxdr/MyUnion.scala:25: warning: match may not be exhaustive.
    It would fail on the following input: UnionKey()
      def decode(stream: XdrDataInputStream): MyUnion = UnionKey.decode(stream) match {
                                                                       ^
    one warning found
    

    因为没有其他的实例 UnionKey . 为什么我会收到这个警告?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Vladimir Matveev    6 年前

    我认为问题是即使 UnionKey sealed 它仍然是 class ,这不会阻止创建它的新实例。这意味着你必须处理 联合密钥 在你 match . 建造师 private 没有帮助,因为scala编译器仍然无法确保您不会在代码中创建其他实例——它需要在最一般的情况下执行代码,而编译器显然不会这样做。

    你能做的就是改变 abstract class 以下内容:

    sealed abstract class UnionKey private (val i: Int)
    

    抽象类不能被实例化,并且可以静态地证明除了派生的case对象之外没有其他实例,因此不会出现警告。下面是一个玩具例子: https://scastie.scala-lang.org/ue3obXY9SUOmLSKRFw4mcg 尝试删除 abstract 例如,在其中,您将再次看到警告。