case class inheritance

Scala 禁止case class inheritance

case class Person(name: String, age: Int)
case class FootballPlayer(name: String, age: Int, number: Int) extends Person(name, age)

在编译时会报出以下错误:

Error:(5, 12) case class FootballPlayer has case ancestor Person, but case-to-case inheritance is prohibited. To overcome this limitation, use extractors to pattern match on non-leaf nodes.
case class FootballPlayer(name: String, age: Int, number: Int) extends Person(name, age)
^

原因有挺多,下边的两篇文章讲了下理由,但我还是没明白其中的必要性。

http://tech.schmitztech.com/scala/caseclassinheritence.html

http://stackoverflow.com/questions/11158929/what-is-so-wrong-with-case-class-inheritance



我们可以使得两个case class继承同一个trait来实际于case class继承的行为,但是这样就得自己写extractor了。比如

  sealed trait Person{
    def age: Int
    def name: String
  }
  case class FootballPlayer(name: String, age: Int, number: Int) extends Person
  val torres = FootballPlayer("Fernando Torres", 31, 19)
  val Person(name, age) = torres // can‘t resolve symbal Person

会编译出错, 因为Person是个trait,它并不支持extractor的语法。

需要给Person加个Companion object,像这样

  object Person{
    def unapply(p: Person) = Some((p.name, p.age))
  }

这时就能用extractor了

  val torres = FootballPlayer("Fernando Torres", 31, 19)
  val Person(name, age) = torres


编译器会为case class生成equals方法,但普通类就不会了。

  sealed trait Person{
    def age: Int
    def name: String
  }

  case class FootballPlayer(name: String, age: Int, number: Int) extends Person
  class Doctor(val name: String, val age: Int) extends Person
  val torresA = FootballPlayer("Fernando Torres", 31, 19)
  val torresB = FootballPlayer("Fernando Torres", 31, 19)
  println(torresA == torresB)//true

  val docA = new Doctor("C", 30)
  val docB = new Doctor("C", 30)
  println(docA == docB)//false

这时,当两个FootballPlayer的构造参数相同,它们就相等。但是对于Doctor类来说不是这样了。

当给FootballPlayer这个case class的父类Person定义了equals方法之后,就不是这样了。

 sealed trait Person{self =>
    def age: Int
    def name: String
    override def equals(that: Any):Boolean = {
      that match{
        case p: Person => p.age == self.age && p.name == self.name
        case _ => false
      }
    }
    override def hashCode: Int = {
      var hash = 1
      hash = hash * 31 + age
      hash = hash * 31 + {if(name !=null) name.hashCode else 0}
      hash
    }
  }
  case class FootballPlayer(name: String, age: Int, number: Int) extends Person
  class Doctor(val name: String, val age: Int) extends Person
  val torresA = FootballPlayer("Fernando Torres", 31, 19)
  val torresB = FootballPlayer("Fernando Torres", 31, 19)
  torresA.equals(torresB)
  println(torresA == torresB)//true

  val docA = new Doctor("C", 30)
  val docB = new Doctor("C", 30)
  println(docA == docB) //true

  val footballPlayerC = FootballPlayer("C", 30, 30)
  println(footballPlayerC == docA) //true
  println(footballPlayerC.hashCode())//1958
  println(docA.hashCode())//1958

貌似这时候case class就不会生成equals方法了, 转而使用父类Person的equals方法。并且要记得同时在Person中覆盖hashCode方法,不然就破坏了equals对hashCode的要求。考虑到hashCode和equals要是自己写还是有点麻烦,所以没有必要就不要在case class的父类中实现equals和hashCode方法了。还是让编译器给case class生成equals和hashCode比较简单。

时间: 2024-12-20 07:56:49

case class inheritance的相关文章

TFS 2015 Build Agent failing syncing the repository 获取源码 不全 失败

当我们使用TFS2015d的生成代理时,我们将生成定义加入代理池队列中,但是代理可能无法完全下载我们在TFS代码浏览器中看到的所有目录,这肯定会导致编译失败呀!为什么呢? 原因在于tfscompile这个账号在某个项目的版本控制中,对某个源码目录没有权限 但是不可能啊,我们已经在根节点上给了权限了呀, 是的,你的确给了根目录所有权限,但是仔细观察你会发现,有个关于继承的隐藏开关 如果某个目录勾选了“关闭”,那么这个目录对TFSCOMPILE账号就无权访问,当然生成代理就无法下载咯. 因此,我们还

C#调用C++导出类(转)

由于使用别人的Dll,导出的是一个实体类,在C#里封送很难,百度下,有个朋友回复一篇英文的,虽然不一定使用,但可以作为一个知识点,现把原文贴下: c#调用C++写的dll导出类,包含继承,重载等详细介绍(转载)忘了出处Inheriting From a Native C++ Class in C# Hi, this is Jim Springfield, an architect on the Visual C++ team.  I have blogged in the past about 

Three Sources of a Solid Object-Oriented Design

pingback :http://java.sys-con.com/node/84633?page=0,1 Object-oriented design is like an alloy consisting of a solid grounding in the object-oriented (OO) approach and implementing the best OO practices heavily laced with how to sidestep the OO pitfal

混入和继承的区别

Mixin vs inheritance Ask Question up vote 76 down vote favorite 19 What is the difference between a mixin and inheritance? oop inheritance mixins shareimprove this question edited Jan 7 '12 at 21:18 user142019 asked May 13 '09 at 20:31 Johnd 1,958620

JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-004Table per class hierarchy(@Inheritance..SINGLE_TABLE)、@DiscriminatorColumn、@DiscriminatorValue、@DiscriminatorFormula)

一.结构 You can map an entire class hierarchy to a single table. This table includes columns for all properties of all classes in the hierarchy. The value of an extra type discriminator column or formula identifies the concrete subclass represented by a

Simple JavaScript Inheritance[转]

摘要:这篇文章介绍JavaScript的一种继承方式实现. 原文链接:https://johnresig.com/blog/simple-javascript-inheritance/ I've been doing a lot of work, lately, with JavaScript inheritance – namely for my work-in-progress JavaScript book – and in doing so have examined a number

Inheritance with EF Code First: Part 2 – Table per Type (TPT)

In the previous blog post you saw that there are three different approaches to representing an inheritance hierarchy and I explained Table per Hierarchy (TPH) as the default mapping strategy in EF Code First. We argued that the disadvantages of TPH m

Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

以下三篇文章是Entity Framework Code-First系列中第七回:Entity Framework Code-First(7):Inheritance Strategy 提到的三篇.这三篇文章写的时间有点久远,还是在2010年,提到EF应该在4.1版本之前,使用的还是ObjectContext而不是现在的DbContext,内容供参考 -------------------------------------------------------------------------

use case学习

Use Case:用例图,静态视图的一种,采用参与者和用例作为基本元素,以不同的视角展现系统的功能性需求. 内容参考:1.http://www.cnblogs.com/Yogurshine/archive/2013/01/14/2859248.html 2.http://www.cnblogs.com/ywqu/archive/2009/12/01/1614509.html 本人大四,求一份寒假期间互联网公司的实习.本人熟悉JavaWeb的开发,有意者私聊,谢谢 一:涉及的主要概念: 参与者(A