Scala Trait

大多数的时候,Scala中的trait有点类似于Java中的interface。正如同java中的class可以implement多个interface,scala中的calss也可以extend多个trait。因此你看你会看到类似于这样的代码:

 class Woodpecker extends Bird with TreeScaling with Pecking

scala的trait具有比java中的interface强大的多的功能,正如同java中的abstract class可以具有一些方法实现一样,scala中的trait也可以拥有implemented methods。但是和java中的abstract class不相同的是,你可以将多个trait糅合到一个class中,也可以控制哪些class可以将trait糅合进去。

trait BaseSoundPlayer {
def play
def close
def pause
def stop
def resume
}

如果方法不需要任何的参数的话,那么就可以使用def只declare方法的名字,而不需要()。当然如果方法需要参数的话,那么和平时一样,加上括号:

trait Dog {
def speak(whatToSay: String)
def wagTail(enabled: Boolean)
}

当一个类继承一个trait的时候,使用的是extend关键字,如果需要集成多个trait的时候,那么需要使用extendwith关键字,也就是第一个trait使用extend,后续的都是用with。如下面的例子:

class Mp3SoundPlayer extends BaseSoundPlayer {...}

class Foo extends BaseClass with Trait1 with Trait2 { ...}

但是如果一个class已经extend另外一个class了,那么如果还想继承其他的trait的话,都必须使用with:

abstract class Animal {

}

trait WaggingTail {
def startTail { println("tail started") }
def stopTail { println("tail stopped") }
} trait FourLeggedAnimal {
def walk
def run
} class Dog extends Animal with WaggingTail with FourLeggedAnimal {
// implementation code here ...
def speak { println("Dog says 'woof'") }
def walk { println("Dog is walking") }
def run { println("Dog is running") }
}

如果一个class extends一个trait,如果它并没有全部实现trait中定义的抽象方法,那么这个class就必须标记为abstract。

class Mp3SoundPlayer extends BaseSoundPlayer {
def play { // code here ... }
def close { // code here ... }
def pause { // code here ... }
def stop { // code here ... }
def resume { // code here ... }
} // must be declared abstract because it does not implement
// all of the BaseSoundPlayer methods
abstract class SimpleSoundPlayer extends BaseSoundPlayer {
def play { ... }
def close { ... }
}

另外,trait也可以extend其他的trait

trait Mp3BaseSoundFilePlayer extends BaseSoundPlayer{
def getBasicPlayer: BasicPlayer
def getBasicController: BasicController
def setGain(volume: Double)
}

定义一个trait,然后给他定义一个faild并且给初始化值,就意味着让它concrete,如果不给值的话,就会让他abstract。

trait PizzaTrait {
var numToppings: Int // abstract
var size = 14 // concrete
val maxNumToppings = 10 // concrete
}

然后对于extends这个PizzaTrait的类中,如果没有给abstract field给值的话,那么就必须标记这个类为abstract、

class Pizza extends PizzaTrait {
var numToppings = 0 // 'override' not needed
size = 16 // 'var' and 'override' not needed
}

从上面的例子可以看出,在trait中可以使用var或者val来定义faild,然后在subclass或者trait中不必使用override关键字来重写var faild。但是对于val faild需要使用override关键字。

trait PizzaTrait {
val maxNumToppings: Int
} class Pizza extends PizzaTrait {
override val maxNumToppings = 10 // 'override' is required
}

尽管scala中也有abstract class,但是使用trait更加的灵活.

如果我们想限制那些class可以嵌入trait的话,我们可以使用下面的语法:

 trait [TraitName] extends [SuperThing]

这样只有extend了SuperThing类型的trait, class, abstract class才能够嵌入TraitName, 比如:

class StarfleetComponent
trait StarfleetWarpCore extends StarfleetComponent
class Starship extends StarfleetComponent with StarfleetWarpCore

另外一个例子:

abstract class Employee
class CorporateEmployee extends Employee
class StoreEmployee extends Employee trait DeliversFood extends StoreEmployee
// this is allowed
class DeliveryPerson extends StoreEmployee with DeliversFood
// won't compile
class Receptionist extends CorporateEmployee with DeliversFood

如果我们想使得Trait只能够被继承了特定类型的类型使用的时候,就可以使用下面的样例:

For instance, to make sure a StarfleetWarpCore can only be used in a Starship , mark the StarfleetWarpCore trait like this:

trait StarfleetWarpCore {
this: Starship =>
// more code here ...
} class Starship
class Enterprise extends Starship with StarfleetWarpCore trait WarpCore {
this: Starship with WarpCoreEjector with FireExtinguisher =>
}

表名WarpCore 只能被同时继承了Starship 、WarpCoreEjector 、WarpCoreEjector 这三个东西的东西嵌入

class Starship
trait WarpCoreEjector
trait FireExtinguisher
// this works
class Enterprise extends Starship
with WarpCore
with WarpCoreEjector
with FireExtinguisher

如果我们想限制Trait只能被拥有特定方法的类型所嵌入的话,可以参考下面的例子:

trait WarpCore {
this: { def ejectWarpCore(password: String): Boolean } =>
}

只有定义有ejectWarpCore方法的classes才能嵌入WarpCore

class Starship {
// code here ...
} class Enterprise extends Starship with WarpCore {
def ejectWarpCore(password: String): Boolean = {
if (password == "password") {
println("ejecting core")
true
} else {
false
}
}
}

当然也可以要求必须有多个方法:

trait WarpCore {
this: {
def ejectWarpCore(password: String): Boolean
def startWarpCore: Unit
} =>
} class Starship
class Enterprise extends Starship with WarpCore {
def ejectWarpCore(password: String): Boolean = {
if (password == "password") { println("core ejected"); true } else false
}
def startWarpCore { println("core started") }
}

我们可以在object instance创建的时候嵌入Traits。

class DavidBanner
trait Angry {
println("You won't like me ...")
} object Test extends App {
val hulk = new DavidBanner with Angry
}

这个代码将会输出:“You won’t like me ...”

这个技巧对于debug一些东西的时候比较方便:

trait Debugger {
def log(message: String) {
// do something with message
}
}
// no debugger
val child = new Child
// debugger added as the object is created
val problemChild = new ProblemChild with Debugger

如果你想在Scala中implement Java interface,看下面的例子;

假定现在有3个java interface:

// java
public interface Animal {
public void speak();
}
public interface Wagging {
public void wag();
}
public interface Running {
public void run();
}

我们在Scala中就可以使用类似于下面的写法

// scala
class Dog extends Animal with Wagging with Running {
def speak { println("Woof") }
def wag { println("Tail is wagging!") }
def run { println("I'm running!") }
}

参考资料

Scala Trait的更多相关文章

  1. scala的trait执行报错: 错误: 找不到或无法加载主类 cn.itcast.scala.`trait`

    scala的trait执行报错: 错误: 找不到或无法加载主类 cn.itcast.scala.`trait`.Children 原因:包名写成了trait,与trait关键字重名了: package ...

  2. Scala trait特质 深入理解

    Scala trait特质 深入理解 初探Scala 特质trait 在Scala中,trait(特质)关键字有着举足轻重的作用.就像在Java中一样,我们只能在Scala中通过extends进行单一 ...

  3. 学习scala trait

      // 类接口,但是可以实现方法 // 作用 多重继承 trait traitA{ val tnum: Int def log(msg: String): Unit ={ println(" ...

  4. Beginning Scala study note(7) Trait

    A trait provides code reusability in Scala by encapsulating method and state and then offing possibi ...

  5. Scala入门系列(八):面向对象之trait

    基础知识 1 将trait作为接口使用 此时Trait就与Java中的接口非常类似,不过注意,在Scala中无论继承还是trait,统一都是extends关键字. Scala跟Java 8前一样不支持 ...

  6. 【Scala篇】--Scala中Trait、模式匹配、样例类、Actor模型

    一.前述 Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大. 模式匹配机制相当于java中的switch-case. 使用了case关键字的类定义就是样例类(case ...

  7. 【Scala学习之二】 Scala 集合 Trait Actor

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

  8. 8、scala面向对象编程之Trait

    一.Trait基础 1.将trait作为接口使用 // Scala中的Triat是一种特殊的概念 // 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似 // 在t ...

  9. Beginning Scala study note(9) Scala and Java Interoperability

    1. Translating Java Classes to Scala Classes Example 1: # a class declaration in Java public class B ...

随机推荐

  1. NVelocity学习笔记一——linq2sql+NVelocity完整demo

    (一)前言      刚刚进入新公司,看公司的项目,发现开发流程几乎和以前的完全不同,再看看页面布局竟然没有发现html.神马情况????一番探究发现使用了NVelocity模板引擎开发的.于是乎花了 ...

  2. 端口被占用的解决方案 sql server 10048 错误

    一大早发现sql server服务无法启动,10048错误,一查是端口占用. 先找到哪个进程,结束即可. cmd命令, netstat /ano|findset "1433" 出现 ...

  3. 似魔鬼的 『 document.write 』

    在平时的工作中,楼主很少用 document.write 方法,一直觉得 document.write 是个危险的方法.楼主不用,并不代表别人不用,最近给维护的项目添了一点代码,更加深了我对 &quo ...

  4. xml入门

    1.why xml? 如果说JSON是一种轻量级的数据交换格式,那么xml就是重量级的.xml应用于web开发的许多方面,常用于简化数据的存储和共享.永远要记住,xml跟JSON一样是用来存储和传输数 ...

  5. 你能熟练使用Dictionary字典和List列表吗?(转)

    命名空间System.Collections.Generic中有两个非常重要,而且常用的泛型集合类,它们分别是Dictionary<TKey,TValue>字典和List<T> ...

  6. jvm中的动态分派

    动态分派与复写密不可分,因为java中存在向上转型,这样就涉及到方法的调用问题.先看一下示例代码 package com.dy.xidian; class Test1 { public void sa ...

  7. 如何实现侧边栏菜单之间的分割线——不用border-bottom

    相信大家都遇到过这样一个老生常谈的问题,就是如果当我们所要做的菜单是侧边栏,垂直方向自上而下的排列的菜单栏,我们在做的时候通常的构想是这样的,就是在每两个菜单之间添加分割线,通常的想法就是说给每个菜单 ...

  8. 【JavaEE企业应用实战学习记录】requestListener

    package sanglp.servlet; import javax.servlet.*; import javax.servlet.annotation.WebListener; import ...

  9. clean之后R文件消失

    首先确定你的SDK是新的. 其次接下来检查你的.xml文件,文件名不能大写. 如果xml文件太多 ,那么clean一下你的项目,这时候注意看Console的提示. Console会提示你xml文件错误 ...

  10. Day Five (beta)

    站立式会议 站立式会议内容总结 331 今天:爬虫抓取豆瓣数据; 明天:数据展示在话题详情页,话题页修改 442 今天:了解聊天模块 遇到的问题:无 明天:编写聊天模块 439 今天:学习 遇到困难 ...