我不明白模式匹配的一个方面。
在模式匹配的文档中,他们显示了一个示例,例如:
https://docs.scala-lang.org/tour/pattern-matching.html
abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification
def showNotification(notification: Notification): String = {
notification match {
case Email(sender, title, _) =>
s"You got an email from $sender with title: $title"
case SMS(number, message) =>
s"You got an SMS from $number! Message: $message"
case VoiceRecording(name, link) =>
s"You received a Voice Recording from $name! Click the link to hear it: $link"
}
}
val someSms = SMS("12345", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
Run Code Online (Sandbox Code Playgroud)
可以用 java 重新编码,例如:
Notification notification = /* Init a notification instance */
if(notification instanceof Email) {
Email currentEmail = (Email) notification;
currentEmail.doSomething();
} else if (notification instanceof SMS) {
SMS currentSMS = (SMS) notification;
currentSMS.doSomething();
} else if {
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
模式匹配似乎被非常积极地看待,但相反,Java 等价物被视为“代码味道”或糟糕的模式。
据我了解,他们正在做同样的事情,也许技术上也是如此,它只是为了 scala 模式匹配而隐藏。
但这样的双重标准是不会消失的,所以我想我的理解有问题。
Lev*_*sey 11
在底层,Scala 模式匹配通常可以归结为与 Java 代码完全相同的代码if (notification instanceof Email) { ... } else if (notification instanceof SMS)。
您给出的特定示例中, Scala 代码abstract class Notification并不比/树sealed更好(除了可能更清楚地表达整体意图)。ifinstanceof
这是因为模式匹配的主要好处是可以进行穷举检查。使用if/instanceof方法和您提供的模式匹配示例,您不会被提醒您尚未处理所有情况(例如,您没有处理该VoiceRecording情况)。
通过制作Notification sealed(例如sealed abstract class Notification),Scala 编译器将确保其他文件(从技术上讲,编译单元,用于所有意图和目的文件)中的 Scala 代码不能扩展Notification;因为它现在知道所有可能的Notifications,所以如果您错过了一个案例,它可能会引发编译器错误。if在/情况下没有可靠的方法来执行此操作,instanceof因为这是较低的抽象级别。