Scala入门到精通——第十节 Scala类层次结构、Traits初步
2015-07-25 22:39
627 查看
本节主要内容
Scala类层次结构总览Scala中原生类型的实现方式解析
Nothing、Null类型解析
Traits简介
Traits几种不同使用方式
1 Scala类层次结构
Scala中的类层次结构图如下:来源:Programming in Scala
从上面的类层次结构图中可以看到,处于继承层次最顶层的是Any类,它是scala继承的根类,scala中所有的类都是它的子类
Any类中定义了下面几个方法:
//==与!=被声明为final,它们不能被子类重写 final def ==(that: Any): Boolean final def !=(that: Any): Boolean def equals(that: Any): Boolean def hashCode: Int def toString: String
从上面的代码看可以看到,Any类中共包括了五个方法,其中==与!=被声明为final类型的,因此它们不能被子类重写,事实上==的真正实现是通过equals方法来实现的,而!=是通过!equals来实现的,因此如果想改变==与!=方法的行为的话,可以直接对equals进行重写。
根类Any有两个子类,它们分别是AnyVal和AnyRef,其中AnyVal是所有scala内置的值类型( Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit.)的父类,其中 Byte, Short, Char, Int, Long, Float, Double, Boolean与java中的byte,short,char,int,long,float,double,boolean原生类型对应,而Unit对应java中的void类型,由于( Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit)继承AnyVal,而AnyVal又继承Any,因此它们也可以调用toString等方法。
scala> 2.0.hashCode res5: Int = 1073741824 scala> 2.0 toString res6: String = 2.0
值得一提的是,()可以作为Unit类型的实例,它同样可以调用toString等方法
scala> ().hashCode res7: Int = 0 scala> ().toString res8: String = () scala> ()==() <console>:8: warning: comparing values of types Unit and Unit using `==' will al ways yield true ()==() ^ res9: Boolean = true
AnyRef是Any的另外一个子类,它是scala中所有非值类型的父类,对应Java.lang.Object类(可以看作是java.lang.Object类的别名),也即它是所有引用类型的父类(除值类型外)。那为什么不直接Java.lang.Object作为scala非值引用类型的父类呢?这是因为Scala还可以运行在其它平台上如.Net,所以它使用了AnyRef这个类,在JVM上它对应的是java.lang.Object,而对于其它平台有不同的实现。
2 Scala中原生类型的实现方式解析
scala采用与java相同原生类型存储方式,由于性能方面及与java进行操作方面的考虑,scala对于原生类型的基本操作如加减乘除操作与java是一样的,当需要遇到其他方法调用时,则使用java的原生类型封装类来表示,如Int类型对应于java.lang.Integer类型,这种转换对于我们使用者来说是透明的。在本课程的第二节中我们提到,scala中的==操作它不区分你是原生类型还是引用类型,例如
scala> "abc"=="abc" res10: Boolean = true
如果是在java语言中,它返回的是false。在scala中,对于原生类型,这种等于操作同java原生类型,而对于引用类型,它实际上是用equals方法对==方法进行实现,这样避免了程序设计时存在的某些问题。那如果想判断两个引用类型是否相等时怎么办呢? AnyRef中提供了eq、ne两个方法用于判断两个引用是否相等,如
scala> val x=new String("123") x: String = 123 scala> val y=new String("123") y: String = 123 scala> x==y res15: Boolean = true scala> x.eq(y) res16: Boolean = false scala> x ne y res17: Boolean = true
3 Nothing、Null类型解析
在前面的类层次结构图中可以看到,Null类型是所有AnyRef类型的子类型,也即它处于AnyRef类的底层,对应java中的null引用。而Nothing是scala类中所有类的子类,它处于scala类的最底层。这里面必须注意的是Null类型处于AnyRef类的底层,它不能够作为值类型的子类,例如:
scala> var x:Int=null <console>:7: error: type mismatch; found : Null(null) required: Int Note that implicit conversions are not applicable because they are ambiguous: both method Integer2intNullConflict in class LowPriorityImplicits of type (x: N ull)Int and method Integer2int in object Predef of type (x: Integer)Int are possible conversion functions from Null(null) to Int var x:Int=null ^
Nothing这个类一般用于指示程序返回非正常结果,利用Nothing作为返回值可以增加程序的灵活性。例如:
def error(msg:String):Nothing={ throw new RuntimeException(msg) } def divide(x: Int, y: Int): Int = if (y != 0) x / y else error("can't divide by zero")
4 Traits简介
scala和java语言一样,采用了很强的限制策略,避免了多种继承的问题。在java语言中,只允许继承一个超类,该类可以实现多个接口,但java接口有其自身的局限性:接口中只能包括抽象方法,不能包含字段、具体方法。Scala语言利用Trait解决了该问题,在scala的trait中,它不但可以包括抽象方法还可以包含字段和具体方法。trait的示例如下://trait定义演示 trait DAO{ //定义一个抽象方法,注意不需要加abstract //加了abstract反而会报错 def delete(id:String):Boolean def add(o:Any):Boolean def update(o:Any):Int def query(id:String):List[Any] }
生成的字节码文件反编译后的结果:
D:\ScalaWorkspace\ScalaChapter10\bin\cn\scala\xtwy>javap -private DAO.class Compiled from "Dao.scala" public interface cn.scala.xtwy.DAO { public abstract boolean delete(java.lang.String); public abstract boolean add(java.lang.Object); public abstract int update(java.lang.Object); public abstract scala.collection.immutable.List<java.lang.Object> query(java.l ang.String); }
下面的代码演示了如果使用trait
trait MysqlDAO{ def add(o:Any):Boolean def update(o:Any):Int def query(id:String):List[Any] } class DaoImpl extends MysqlDAO{ def add(o:Any):Boolean=true def update(o:Any):Int= 1 def query(id:String):List[Any]=List(1,2,3) }
如果有多个trait的话:
trait MysqlDAO{ var recodeMount:Long=15000000000000L def add(o:Any):Boolean def update(o:Any):Int def query(id:String):List[Any] } class DaoImpl extends MysqlDAO with Cloneable{ def add(o:Any):Boolean=true def update(o:Any):Int= 1 def query(id:String):List[Any]=List(1,2,3) }
5 Traits几种不同使用方式
1 当做java接口使用的trait,如//trait定义演示 trait DAO{ //定义一个抽象方法,注意不需要加abstract //加了abstract反而会报错 def delete(id:String):Boolean def add(o:Any):Boolean def update(o:Any):Int def query(id:String):List[Any] }
2 带具体实现的trait
trait DAO{ //delete方法有具体实现 def delete(id:String):Boolean={ println("delete implementation") true } def add(o:Any):Boolean def update(o:Any):Int def query(id:String):List[Any] }
这里定义的特质将生成两个字节码文件:
D:\ScalaWorkspace\ScalaChapter10\bin\cn\scala\xtwy 的目录 2015/07/25 22:20 <DIR> . 2015/07/25 22:20 <DIR> .. 2015/07/25 22:20 575 DAO$class.class 2015/07/25 22:20 898 DAO.class 2 个文件 1,473 字节 2 个目录 175,333,232,640 可用字节 D:\ScalaWorkspace\ScalaChapter10\bin\cn\scala\xtwy>javap -private DAO$class.class Compiled from "Dao.scala" public abstract class cn.scala.xtwy.DAO$class { public static boolean delete(cn.scala.xtwy.DAO, java.lang.String); public static void $init$(cn.scala.xtwy.DAO); } D:\ScalaWorkspace\ScalaChapter10\bin\cn\scala\xtwy>javap -private DAO.class Compiled from "Dao.scala" public abstract class cn.scala.xtwy.DAO$class { public static boolean delete(cn.scala.xtwy.DAO, java.lang.String); public static void $init$(cn.scala.xtwy.DAO); }
从字节码文件可以看出,带有具体实现的trait是通过java中的抽象类来实现的。
3 带抽象字段的trait
trait DAO{ var recodeMount:Long def delete(id:String):Boolean={ println("delete implementation") true } def add(o:Any):Boolean def update(o:Any):Int def query(id:String):List[Any] }
4 具体字段的trait
trait DAO{ var recodeMount:Long=15000000000000L def delete(id:String):Boolean={ println("delete implementation") true } def add(o:Any):Boolean def update(o:Any):Int def query(id:String):List[Any] }
添加公众微信号,可以了解更多最新Spark、Scala相关技术资讯
相关文章推荐
- Container With Most Water (头尾指针的妙用)
- synchronized , wait() , notify() and notifyAll()
- Climbing Stairs
- strcpy,strncpy http://blog.csdn.net/shutear/article/details/8256096
- int main(int argc, char*argv[])
- 2015 Multi-University Training Contest 2 hdu 5308 I Wanna Become A 24-Point Master
- ECHOSRV.C中的main()设立一个 I/O completion port
- 【bzoj4152】 AMPPZ2014The Captain 最短路
- 一刀斩 :“SVN” failed to start 服务启动失败
- UVA - 10976 Fractions Again?!
- centos中w使用smbclient连接window出现:session setup failed: NT_STATUS_LOGON_FAILURE
- 二分搜索 HDOJ 2675 Equation Again
- 模拟器报Installation error: INSTALL_FAILED_CONTAINER_ERROR解决方法
- hdoj 2647 N!Again
- 人工智能的策略,如果国家优先发展”梦想成真”?
- Linux中的文件描述符与打开文件之间的关系 :http://blog.csdn.net/cywosp/article/details/38965239
- 关于Flash中的黑白棋AI编写心得
- Snail—OC学习之类别Category
- [leetcode ]220.Contains Duplicate III
- Snail—OC学习之空变量的表示