【问题标题】:Scala wont pattern match with java.lang.String and Case ClassScala 不会与 java.lang.String 和 Case Class 进行模式匹配
【发布时间】:2011-02-08 18:26:17
【问题描述】:

各位 Scala 程序员大家好

我已经使用 Scala 工作了一个月,但是我在一些基本的东西上遇到了问题,我希望你能帮我解决这个问题。

case class PersonClass(name: String, age: Int)

object CaseTester {
def main(args:Array[String])
 {
  val string = "hej"
  string match {
    case e:String => println(string)
    case PersonClass => println(string)
  }
 }
}

当我这样做时,我得到错误:

pattern type is incompatible with expected type;
found   : object PersonClass
required: java.lang.String
case PersonClass => println(string)

如果我将模式匹配中的第二行更改为以下内容:

case e:PersonClass => println(string)

然后我得到错误:

error: scrutinee is incompatible with pattern type;
found   : PersonClass
required: java.lang.String
case e:PersonClass => println(string)

但是,如果我将字符串定义更改为以下内容,它在两种情况下都可以正常编译。

val string:AnyRef = "hej"

【问题讨论】:

  • 最初我在尝试制作案例类时遇到了这个问题,它也应该能够成为提取器,但是当我想到它并没有多大意义:)
  • 你无法匹配这样的课程。 case PersonClass => 仅在 PersonClass 是一个对象时才有效。要匹配类,您可以分配给一个局部变量:case e: String =>,或者如果它是一个元组或案例类,则解包:(3, 4) match { case (a, b) =>

标签: scala types pattern-matching case-class


【解决方案1】:

推断的字符串类型是String。这是在声明 val 之后才知道的。

正如我们在模式匹配过程中已经知道的那样,匹配不是字符串的模式(如您的 PersonClass)是没有意义的,因为它们永远不会匹配。这就是“模式类型与预期类型不兼容;发现:object PersonClass required: java.lang.String case PersonClass => println(string)”错误意味着:我们期望一个模式是 String 的子类,但发现了一些东西 ( PersonClass) 不是。

当您强制键入 AnyRef 时,情况会发生变化。编译器会将字符串视为 Anyref,因此扩展 AnyRef 的模式可能会匹配。 PersonClass 是 AnyRef,因此不会出错。

【讨论】:

    【解决方案2】:

    如果您已经有一个 String 类型的对象,它将永远不会匹配 PersonClass 类型。实际上,编译器不允许您执行这些永远不会成功的匹配的功能。

    使用 Any 类型,您只需关闭类型检查。它与此定义不匹配,但编译器无法捕获此问题。

    【讨论】:

      【解决方案3】:

      我假设您正在尝试测试其他内容,但编译器太聪明了,无法让您测试。

      也许你想要这样的东西:

      object Test {
        case class Person(name: String, age: Int) { }
        def myPrint(ar: AnyRef) {
          ar match {
            case s: String => println(s)
            case Person(name, age) => println("My name is "+name)
            case _ => println("I am a mystery!")
          }
        }
        def test = {
          myPrint("Hello, World")
          myPrint(Person("John Doe",40))
          myPrint(5)
        }
      }
      

      但正如其他人指出的那样,如果您实际上不需要检查其他类型,编译器会抱怨您所做的事情毫无意义。这也是一件好事:如果您不编写测试,您可能会遇到难以调试的运行时错误。

      【讨论】:

        【解决方案4】:
        object ws {
        
        case class PersonClass(name:String,age: Int)
        val p=new PersonClass("ach",25)                    
        
          def string(x: Any) = x match {
            case x:String => println(x)
            case x:PersonClass => println(p.name +" "+p.age)
           }                                              
        
             string("aa")                                 //> aa
             string(p)                                    //> ach 25
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-11
          • 2015-04-02
          • 1970-01-01
          • 2021-06-15
          • 1970-01-01
          相关资源
          最近更新 更多