首页 文章

如何模式匹配继承树中的抽象父类

提问于
浏览
3

我是scala的新手,拥有java背景 .

有没有办法在类继承树中模式匹配超类(或特征),叶子作为案例类和节点抽象类或特征?据我所知,不允许使用case类继承 .

我认为在大型继承树中匹配抽象类的模式会非常有用

在下面的代码中,编译期间匹配语句错误的最后一种情况

sealed trait Person {
   def name: String
}

case class Customer(name: String, email: String) extends Person

sealed trait Employee extends Person {
   def id: Int
}

case class Worker(name: String, id: Int, skills: Array[String]) extends Employee

case class Manager(name: String, id: Int, title: String) extends Employee

def process(p: Person) = p match {
   case Customer(_, email) => email
   case Employee(name, _) => name + "@acme.com"
}

2 回答

  • 1

    您错过了 Employee 中的 name 字段和 Employee 的配套对象中的 unapply 方法:

    sealed trait Employee extends Person {
      def id: Int
      def name: String
    }
    
    object Employee {
      def unapply(e: Employee): Option[(String, Int)] =
        Option(e) map { e =>
          (e.name, e.id)
        }
    }
    

    通过上述更改,处理方法没有出现任何问题:

    def process(p: Person) = p match {
      case Customer(_, email) => email
      case Employee(name, _) => name + "@acme.com"
    }
    
  • 5

    这不是那种幻想(正如其他人可能建议的结构类型),但我认为它非常实用:

    def process(p: Person) = p match {
       case Customer(_, email) => email
       case e: Employee => e.name + "@acme.com"
    }
    

    如果您需要匹配一些特定的已知值,您可以使用警卫:

    def process(p: Person) = p match {
       case Customer(_, email) => email
       case e: Employee if e.name == "Joe" => e.name + "@acme.com"
    }
    

相关问题