博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
case class inheritance
阅读量:5062 次
发布时间:2019-06-12

本文共 2933 字,大约阅读时间需要 9 分钟。

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的要求。

转载于:https://www.cnblogs.com/devos/p/4451935.html

你可能感兴趣的文章
学习python:day1
查看>>
css3动画属性
查看>>
第九次团队作业-测试报告与用户使用手册
查看>>
Mongodb 基本命令
查看>>
控制文件的备份与恢复
查看>>
返回代码hdu 2054 A==B?
查看>>
iOS 8 地图
查看>>
iOS 日常工作之常用宏定义大全
查看>>
PHP的SQL注入技术实现以及预防措施
查看>>
软件目录结构规范
查看>>
mysqladmin
查看>>
解决 No Entity Framework provider found for the ADO.NET provider
查看>>
Android 自定义View (三) 圆环交替 等待效果
查看>>
设置虚拟机虚拟机中fedora上网配置-bridge连接方式(图解)
查看>>
HEVC播放器出炉,迅雷看看支持H.265
查看>>
[置顶] Android仿人人客户端(v5.7.1)——人人授权访问界面
查看>>
Eclipse 调试的时候Tomcat报错启动不了
查看>>
【安卓5】高级控件——拖动条SeekBar
查看>>
ES6内置方法find 和 filter的区别在哪
查看>>
Android入门之文件系统操作(二)文件操作相关指令
查看>>