Scala入门到精通——第十节 Scala类层次结构、Traits初步

本节主要内容

  1. Scala类层次结构总览
  2. Scala中原生类型的实现方式解析
  3. Nothing、Null类型解析
  4. Traits简介
  5. 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> val x:Int=Null
<console>:7: error: not found: value Null
       val 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相关技术资讯

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 18:12:57

Scala入门到精通——第十节 Scala类层次结构、Traits初步的相关文章

Scala入门到精通——第二十节 类型參数(二)

本节主要内容 Ordering与Ordered特质 上下文界定(Context Bound) 多重界定 类型约束 1. Ordering与Ordered特质 在介绍上下文界定之前,我们对scala中的Ordering与Ordered之间的关联与差别进行解说,先看Ordering.Ordered的类继承层次体系: 通过上面两个图能够看到,Ordering混入了java中的Comparator接口.而Ordered混入了java的Comparable接口.我们知道java中的Comparator是一

Scala入门到精通——第二十节 类型参数(二)

本节主要内容 Ordering与Ordered特质 上下文界定(Context Bound) 多重界定 类型约束 1. Ordering与Ordered特质 在介绍上下文界定之前,我们对scala中的Ordering与Ordered之间的关联与区别进行讲解,先看Ordering.Ordered的类继承层次体系: 通过上面两个图可以看到,Ordering混入了java中的Comparator接口,而Ordered混入了java的Comparable接口,我们知道java中的Comparator是一

Scala入门到精通——第二十七节 Scala操纵XML

本节主要内容 XML 字面量 XML内容提取 XML对象序列化及反序列化 XML文件读取与保存 XML模式匹配 1. XML 字面量 XML是一种非常重要的半结构化数据表示方式,目前大量的应用依赖于XML,这些应用或利用XML作为数据交换格式,或利用XML进行文件配置等.像JAVA.C++及其它流行的程序开发语言都是依赖于第三方库来实现XML的操作,例如JAVA经常通过JDOM,DOM4J等XML处理工具进行XML的操纵,但Scala提供了对XML的原生支持,通过scala.xml._包下的类或

Scala入门到精通——第二十八节 Scala与JAVA互操作

本节主要内容 JAVA中调用Scala类 Scala中调用JAVA类 Scala类型参数与JAVA泛型互操作 Scala与Java间的异常处理互操作 1. JAVA中调用Scala类 Java可以直接操作纵Scala类,如同Scala直接使用Java中的类一样,例如: //在Person.scala文件中定义Scala语法的Person类 package cn.scala.xtwy.scalaToJava class Person(val name:String,val age:Int) //伴

Scala入门到精通——第十四节 Case Class与模式匹配(一)

本节主要内容 模式匹配入门 Case Class简介 Case Class进阶 1. 模式匹配入门 在java语言中存在switch语句,例如: //下面的代码演示了java中switch语句的使用 public class SwitchDemo { public static void main(String[] args) { for(int i = 0; i < 100; i++) { switch (i) { case 10:System.out.println("10"

Scala入门到精通——第十五节 Case Class与模式匹配(二)

本节主要内容 模式匹配的类型 for控制结构中的模式匹配 option类型模式匹配 1. 模式的类型 1 常量模式 object ConstantPattern{ def main(args: Array[String]): Unit = { //注意,下面定义的是一个函数 //函数的返回值利用的是模式匹配后的结果作为其返回值 //还需要注意的是函数定义在main方法中 //也即scala语言可以在一个函数中定义另外一个函数 def patternShow(x:Any)=x match { ca

Scala入门到精通——第二十五节 提取器(Extractor)

作者:摇摆少年梦 视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 apply与unapply方法 零变量或变量的模式匹配 提取器与序列模式 scala中的占位符使用总结 1. apply与unapply方法 apply方法我们已经非常熟悉了,它帮助我们无需new操作就可以创建对象,而unapply方法则用于析构出对象,在模式匹配中特别提到,如果一个类要能够应用于模式匹配当中,必须将类声明为case class,因为一旦被定义为case class,

Scala入门到精通——第二十四节 高级类型 (三)

作者:摆摆少年梦 视频地址:http://blog.csdn.net/wsscy2004/article/details/38440247 本节主要内容 Type Specialization Manifest.TypeTag.ClassTag Scala类型系统总结 在scala中,类(class)与类型(type)是两个不一样的概念.我们知道类是对同一类型数据的抽象,而类型则更详细. 比方定义class List[T] {}, 能够有List[Int] 和 List[String]等详细类型

Scala入门到精通——第二十九节 Scala数据库编程

本节主要内容 Scala Mavenproject的创建 Scala JDBC方式訪问MySQL Slick简单介绍 Slick数据库编程实战 SQL与Slick相互转换 本课程在多数内容是在官方教程上改动而来的,官方给的样例是H2数据库上的.经过本人改造,用在MySQL数据库上,官方教程地址:http://slick.typesafe.com/doc/2.1.0/sql-to-slick.html 1. Scala Mavenproject的创建 本节的project项目採用的是Maven P