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())//
println(docA.hashCode())//
貌似这时候case class就不会生成equals方法了, 转而使用父类Person的equals方法。并且要记得同时在Person中覆盖hashCode方法,不然就破坏了equals对hashCode的要求。
case class inheritance的更多相关文章
- 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 consis ...
- C#调用C++导出类(转)
由于使用别人的Dll,导出的是一个实体类,在C#里封送很难,百度下,有个朋友回复一篇英文的,虽然不一定使用,但可以作为一个知识点,现把原文贴下: c#调用C++写的dll导出类,包含继承,重载等详细介 ...
- TFS 2015 Build Agent failing syncing the repository 获取源码 不全 失败
当我们使用TFS2015d的生成代理时,我们将生成定义加入代理池队列中,但是代理可能无法完全下载我们在TFS代码浏览器中看到的所有目录,这肯定会导致编译失败呀!为什么呢? 原因在于tfscompile ...
- Ubuntu+apache安装redmin
公司要迁移redmin,本来以为是一个很简单的项目,想不到整整搞了一天加一个晚上. 首先是对ruby的安装不熟悉,现在明白了ruby的安装顺序是先安装rvm版本管理,然后用rvm安装ruby,安装好后 ...
- The IDL compiler
The IDL compiler or bindings generator transcompiles Web IDL to C++ code, specifically bindings betw ...
- C++: virtual inheritance and Cross Delegation
Link1: Give an example Note: I think the Storable::Write method should also be pure virtual. http:// ...
- JavaScript Patterns 6.2 Expected Outcome When Using Classical Inheritance
// the parent constructor function Parent(name) { this.name = name || 'Adam'; } // adding functional ...
- Effective Java 17 Design and document for inheritance or else prohibit it
Principles The class must document its self-use of overridable methods. A class may have to provide ...
- Think Python - Chapter 18 - Inheritance
In this chapter I present classes to represent playing cards, decks of cards, and poker hands.If you ...
随机推荐
- ComboBoxEdit数据绑定
ComboBoxEdit也是DevExpress winform控件中经常使用的一个,我们在使用的过程中可能有时需要对ComboBoxEdit控件进行数据绑定,而ComboBoxEdit控件不像 Lo ...
- JavaScript之图片轮换
<!doctype html> <title>javascript图片轮换</title> <meta charset="utf-8"/& ...
- Ajax之数据连接信息捕获
connDB.properties: DB_CLASS_NAME=com.mysql.jdbc.Driver DB_URL=jdbc:mysql://127.0.0.1:3306/db_datab ...
- ### C++总结-[类的继承]
面向对象中关于继承的总结. #@author: gr #@date: 2015-07-26 #@email: forgerui@gmail.com 一.类的隐藏 重载(overload).覆盖(ove ...
- OC6-网址分割
// // HtmlManger.h // OC6-网址分割 // // Created by qianfeng on 15/6/17. // Copyright (c) 2015年 qianfeng ...
- Java集合源码分析
Java集合工具包位于Java.util包下,包含了很多常用的数据结构,如数组.链表.栈.队列.集合.哈希表等.学习Java集合框架下大致可以分为如下五个部分:List列表.Set集合.Map映射.迭 ...
- (poj 3177) Redundant Paths
题目链接 :http://poj.org/problem?id=3177 Description In order to <= F <= ,) grazing fields (which ...
- Nginx日志按天分割
核心思想:使用crontab在每日23:59执行日志分割. 1.配置nginx日志信息,vim /etc/logrotate.d/nginx /var/log/nginx/*.log { nocomp ...
- SystemFile
header('Content-Type:text/html; charset = utf-8'); 1. echo "<pre/>";echo __FILE__.&q ...
- java 读写锁
http://tutorials.jenkov.com/java-concurrency/read-write-locks.html 翻译 读写锁比LOCK的实现更复杂,想象有一个应用程序能读和写一些 ...