Scala 不会与 java.lang.String 和 Case Class 模式匹配

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2651994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:04:38  来源:igfitidea点击:

Scala wont pattern match with java.lang.String and Case Class

scalatypespattern-matchingcase-class

提问by Stefan

Hello fellow Scala Programmers

你好 Scala 程序员

I have been working with Scala for some month now, however I have a problem with some properly basic stuff, I am hoping you will help my out with it.

我已经用 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)
  }
 }
}

When I am doing like this I get error:

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

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

And if I then change the second line in the pattern matching to the following:

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

case e:PersonClass => println(string)

I then get the error:

然后我得到错误:

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

However if I change the string definition to the following it compiles fine in both cases.

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

val string:AnyRef = "hej"

回答by Sandor Murakozi

The inferred type of string is String. That is known after the declaration of the val.

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

As we already know it during pattern matching it doesn't make sense to match patterns that are not Strings (like your PersonClass), as they will never match. That's what the "pattern type is incompatible with expected type; found : object PersonClass required: java.lang.String case PersonClass => println(string)" error means: we expect a pattern that is a subclass of String, but found something (PersonClass) which is not.

正如我们在模式匹配期间已经知道的那样,匹配不是字符串的模式(比如你的 PersonClass)是没有意义的,因为它们永远不会匹配。这就是“模式类型与预期类型不兼容;发现:需要对象 PersonClass:java.lang.String case PersonClass => println(string)”错误的意思:我们期望模式是 String 的子类,但发现了一些东西( PersonClass) 而不是。

When you force the type AnyRef the situation changes. The compiler will treat string as Anyref, so patterns that extend AnyRef might match. PersonClass is AnyRef, so you don't get error.

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

回答by Thomas Jung

If you already have an object of type String it will never match a type PersonClass. It's actually a feature that the compiler does you not let do these matches that will never succeed.

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

With the Any type you are simply turning the type check off. It won't match with this definition but the compiler can't catch this problem.

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

回答by Rex Kerr

I assume you're trying to test something else, but the compiler is too smart to let you.

我假设您正在尝试测试其他东西,但编译器太聪明了,不能让您测试。

Maybe you want something like this:

也许你想要这样的东西:

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)
  }
}

but as others have pointed out, if you don't actuallyneed to check for the other types, the compiler will complain that what you're doing is pointless. A good thing, too: if you weren't writing a test, you might have a hard-to-debug runtime error.

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

回答by Achraf Arboun

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

}