trait用法汇总
来源:互联网 发布:linux ld错误返回1 编辑:程序博客网 时间:2024/06/16 15:53
trait的功能类似于Java中的interface,但是trait也兼具abstract class的特征,它提供的功能要远比interface和abstract class多很多,以下主要是通过对比trait和interface, abstract class的用法来了解trait的功能。
- trait和interface的区别
- trait和abstract class的区别
- 如何限制哪些class可以继承trait
- 如何让一个instance object mixin一个trait
- trait在什么情况下使用extends和with关键词
trait和interface的区别
trait的第一个功能是定义一些抽象方法,使得继承它的类实现这些方法,这和Java的interface相同。但是,interface只能定义方法的prototype, 不能实现这些方法,而trait可以实现它所定义的方法,甚至是所有方法。从这个意义上来说,trait又有点儿像一个普通的class,但是比class更灵活,一个子类只能extends一个父类,但是一个子类可以with多个trait。如果每个trait的方法都有实现,这就实现了Java中不能同时extends多个class的问题。
trait可以extends或with其他traits。
一旦继承了traits,要么声明为abstract class, 要么实现trait的所有方法和域。
trait Animal { def eat(food: String) // 抽象方法,带一个参数 def run(legs: Int): Unit // 抽象方法, 带一个参数和一个返回值,Unit可省略 def sleep = { //concrete method with no arguemtns println("Hello, I'm sleeping. Do not interrupt me!") }}
trait和abstract class的区别
二者共性在于都可以定义方法,即实现方法,也可以定义变量。不同的是,scala对var和val类型的变量处理方式不同, 是否有赋值也有所区别。
val类型的变量必须在声明时赋值,子类需要override父类的这个变量值时,必须显式的声明位override。var类型的变量如果在声明时没有被赋值,就被认为是abstract类型,那么子类继承该trait后,就必须赋值;如果var类型的变量在声明时有初始值,那么子类可以不重新赋值,也可以赋为其他值,此时不需要override,因为它是variable的。
例如:
trait Animal { val legs = 4 // concrete var liveArea: String // abstract var species = "Crawler" // concrete def run(legs: Int): Unit ...}class Bird extends Animal { override val legs = 2 var liveArea = "everywhere" // 注意,var关键字不能少! def run(legs: Int): Unit = { println(s"I can run with $legs legs, and I can also fly") } ...}
如何限制哪些class可以继承trait
trait有三种方式限制哪些class可以继承它,这是Java无法提供的功能。
- 通过显式定义子类必须要继承哪些类才可以继承该trait,prototype如下:
trait MyTrait { this: BaseType => ....}
任何要继承MyTrait的类,必须是BaseType的子类。
例如:
trait Animal { def eat } trait Fish { this: Animal => } class GoldenFish extends Animal with Fish { def eat = { ... } }
如果GoldenFish直接继承Fish, 会提示如下错误信息:
test.scala:24: error: illegal inheritance;
self-type GoldenFish does not conform to Fish’s selftype Fish with Animal
class GoldenFish extends Fish {
^
one error found
1.通过定义子类必须要实现的方法类限制可以继承的子类
prototype如下:
MyTrait Fish { this: {def swim } => def eat}
任何要继承Fish的类,必须实现swim方法。例如:
class GoldFish extends MyTrait { def swim = { println("I'm swimming") } def eat = { println("what can i eat?") }}
如何让一个instance object mixin一个trait
这个trait的一个特点,可以在创建类实例时将trait mixin。例如我们有如下的trait:
trait Logging { println("start logging") def log(msg: String)}class EmptyClass { def log(msg: String) = {}}val ec = new EmptyClass() with Logging
当执行这行代码后,会打印 “start logging”信息,原因是在创建EmptyClass实例时,Logging自动被继承,构造函数被自动调用。
这对我们添加log信息很有帮助。
trait在什么情况下使用extends和with关键词
规则如下:
如果class只继承一个trait, 那么直接用extends;
如果class继承一个class和一个或多个trait, 那么class用extends, trait用with;
如果class继承多个trait, 第一个trait用extends,其他的用with;
也就是有class优先将extends给该class, with给trait。
- trait用法汇总
- Trait
- trait
- Trait
- trait
- trait
- trait
- trait技术
- Trait技术
- trait,线性化
- c++ trait
- php trait
- Scala:trait
- php trait
- PHP TRAIT
- PHP Trait
- PHP trait
- php trait
- android开源库—retrofit(附实战源码)
- http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed wit
- CentOS安装Mysql-5.7
- stl理解
- 《初入linux》--第十一部分-rpm软件安装与yum的使用与搭建
- trait用法汇总
- 在笔记本上安装CUDA8 & ZED Stereo Camera
- Java高并发编程:多个线程之间共享数据的方式探讨
- BZOJ4012: [HNOI2015]开店
- 修改pip安装源加快python模块安装
- studio中ADB端口被占用,模拟器找不到问题
- CentOS 6.5 安装 Tengine
- FileItem类的常用方法
- 城市列表切换