Scala Trait详解

除了从父类集成代码外,Scala中的类还允许从一个或者多个traits中导入代码。
对于Java程序员来说理解traits的最好方法就是把他们当作可以包含代码的接口(interface)。在Scala中,当一个类继承一个trait时,它就实现了这个trait的接口,同时还从这个trait中继承了所有的代码。
让我们通过一个典型的实例来看看这种trait机制是如何发挥作用的:排序对象。能够比较若干给定类型的对象在实际应用中是很有用的,比如在进行排 序时。在Java语言中可以比较的对象是通过实现Comparable接口完成的 。在Scala中我们可以通过吧Comparable定义为trait来做的比Java好一些。我们吧这个trait叫做Ord。
在比较对象时,一下六种关系通常使用率最高:小于、小于等于、等于、不等于、大于等于、大于。但是把他们都定义一次无疑是很没用而且繁琐的。尤其是 六种关系中的四种其实是可以通过其他两种关系导出的。例如给定等于和小于的定义后就可以推导出其他的定义。于是在Scala中,这些推导可以通过下面这个 trait实现:
trait Ord { def < (that: Any): Boolean def <=(that: Any): Boolean = (this < that) || (this == that) def > (that: Any): Boolean = !(this <= that) def >=(that: Any): Boolean = !(this < that) }
这个定义在建立了一个叫做与Java中的 Comparable 等效的叫做 Ord的类型的同时还实现了使用抽象的一种关系推导其他三种的接口。比较相等性的方法没有出现是由于他已经默认存在于所有对象中了。
上面使用的叫做Any的类型表示了Scala中所有类的共同超类。事实上它就等于Java语言中的Object。
要使的一个类可以被比较,就需要可以比较他们是否相等或者大小关系,而这些都混合在上面的类Ord中了。现在我们来写一个Date类来表示格利高里历中的日期。这个日期由年、月、日三个部分组成,每个部分都可以用一个整数表示。所有我们就得出了下面这个定义:
class Date(y: Int, m: Int, d: Int) extends Ord { def year = y def month = m def day = d override def toString(): String = year + "-" + month + "-" + day }
注意在类名后出现的extends Ord。这表示了这个类继承了Ord这个trait。
然后我们重新定义了equals这个从Object继承来的方法,好让他能够正确的比较我们日期中的每个部分。原来的equals函数的行为与Java中的一样,是按照对象的指针进行比较的。我们可以得出下面的代码。
override def equals(that: Any): Boolean = that.isInstanceOf[Date] && { val o = that.asInstanceOf[Date] o.day == day && o.month == month && o.year == year }
这个函数使用了预定义函数 isInstanceOf 和asInstanceOf 。第一个isInstanceOf 类似Java中的 instanceof :当且仅当对象是给定类型的实例时才返回true。第二个 asInstanceOf 对应Java中的类型转换操作:当对象是给定类型的子类时转换,否则抛出ClassCastException。
最后我们还需要定义测试小于关系的函数,如下面所示。这个函数使用了预定义的函数error ,它可以使用给定字符串抛出一个异常。
def <(that: Any): Boolean = { if (!that.isInstanceOf[Date]) error("cannot compare " + that + " and a Date") val o = that.asInstanceOf[Date] (year < o.year) || (year == o.year && (month < o.month || (month == o.month && day < o.day))) }

以上就是Data的完整定义了。这个类的实例既可以作为日期显示,也可以进行比较。而且他们都定义了6种比较操作:其中两种 : equals和< 是我们直接定义的,而其他的是从Ord中继承的。

更多精彩内容请关注:http://bbs.superwu.cn

关注超人学院微信二维码:

时间: 2024-08-26 15:03:07

Scala Trait详解的相关文章

scala 模式匹配详解 2 scala里是怎么实现的?

在这篇martin和另外两位模式匹配领域专家的论文里说了模式匹配的几种实现方式,以及scala是选择哪种方式来实现的.http://lampwww.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf我引用了里面的一些描述. 在面向对象的程序中数据被组织为一级一级的类(class)面向对象语言在模式匹配方面的问题在于如何从外部探测这个层级. 有6种实现模式匹配的方法:1) 面向对象的分解 (decomposition)2) 访问器模式

scala 模式匹配详解 3 模式匹配的核心功能是解构

http://www.artima.com/scalazine/articles/pattern_matching.html这篇文章是odersky谈scala中的模式匹配的一段对话,我做了部分片段翻译(不是连贯的): 模式可以嵌套,就像表达式嵌套,你可以定义深层的模式,通常一个模式看起来就像一个表达式.它基本上就是同一类事情.它看起来像一个复杂的对象树构造表达式,只是漏掉了new关键字.事实上在scala当你构造一个对象,你不需要new关键字然后你可以在一些地方用变量做站位符替代对象树上实际的

scala collection详解

原帖:http://stackoverflow.com/questions/1722137/scala-2-8-collections-design-tutorial There's a 2.8 collection walk-through by Martin Odersky which should probably be your first reference. It has been supplemented as well with architectural notes, whic

Spark入门到精通--(第二节)Scala编程详解基础语法

Scala是什么? Scala是以实现scaleable language为初衷设计出来的一门语言.官方中,称它是object-oriented language和functional language的混合式语言. Scala可以和java程序无缝拼接,因为scala文件编译后也是成为.class文件,并且在JVM上运行. Spark是由Scala进行开发的. Scala安装? 这里就讲一下Scala在Centos上进行安装的过程,和安装JDK差不多. 官网下载Scala:http://www

Scala类型详解

语法: Type ::= InfixType ?=>? Type | ?(?[?=>? Type] ?)? ?=>? Type | InfixType [ExistentialClause] ExistentialClause ::= ?forSome? ?{?ExistentialDc { semi ExistentialDcl} ?}? ExistentialDcl ::= ?type? TypeDcl | ?val? ValDcl InfixType ::= CompoundTyp

PHP7之Trait详解

转自: https://www.jianshu.com/p/fc053b2d7fd1 php从以前到现在一直都是单继承的语言,无法同时从两个基类中继承属性和方法,为了解决这个问题,php出了Trait这个特性(听说这个Trait和Go语言有点类似,具体没学过Go语言) 用法:通过在类中使用use 关键字,声明要组合的Trait名称,具体的Trait的声明使用Trait关键词,Trait不能实例化 如下代码实例: <?php trait Dog{ public $name="dog"

Scala集合类详解

对scala中的集合类虽然有使用,但是一直处于一知半解的状态.尤其是与java中各种集合类的混合使用,虽然用过很多次,但是一直也没有做比较深入的了解与分析.正好趁着最近项目的需要,加上稍微有点时间,特意多花了一点时间对scala中的集合类做个详细的总结. 1.数组Array 在说集合类之前,先看看scala中的数组.与Java中不同的是,Scala中没有数组这一种类型.在Scala中,Array类的功能就与数组类似. 与所有数组一样,Array的长度不可变,里面的数据可以按索引位置访问. def

Scala 编程详解 ---003 函数入门

一.函数的定义与调用 在Scala中定义函数时,需要定义函数的函数名.参数.函数体. 我们的第一个函数如下所示: def sayHello(name: String, age: Int) = { if (age > 18) { printf("hi %s, you are a big boy\n", name); age } else { printf("hi %s, you are a little boy\n", name); age } sayHello

PHP之Trait详解

php从以前到现在一直都是单继承的语言,无法同时从两个基类中继承属性和方法,为了解决这个问题,php出了Trait这个特性 用法:通过在类中使用use 关键字,声明要组合的Trait名称,具体的Trait的声明使用Trait关键词,Trait不能实例化 如下代码实例: <?php trait Dog{ public $name="dog"; public function bark(){ echo "This is dog"; } } class Animal