Scala trait类
使用方面类似于Java中的Interface接口
特点:
- 声明特质类时,类的类型为
trait
- 特质类中,可以有抽象成员也可以有具体成员;
- 特质类在实现时,如果当前类没有父类使用
extends关键字
,class 类名 extends 特质类1 with 特质类2 with 特质类3 ...
- 特质类在实现时,如果当前类有父类,使用时
class 子类名 extends 父类名 with 特质1 with 特质2 ...
定义
package traits
/**
* 特质类 类似于java的接口
*/
trait Animal {
// 抽象属性
var name: String
// 抽象方法
def eat
}
实现
// 无父类 extends 特质类
class Dog extends Animal {
override var name: String = _
override def eat: Unit = println("dog eating...")
}
object Dog {
def main(args: Array[String]): Unit = {
// 多态 接口引用指向实现类
val a1: Animal = new Dog
a1.eat
}
}
class Person
// 有父类 先继承 父类 在混入特质类
class SmallStudent extends Person with Animal {
override var name: String = _
override def eat: Unit = println("small student eating ...")
}
带有具体实现的特质类
/**
* 特质类 类似于java的接口
*/
trait Animal {
// 抽象属性
var name: String
// 抽象方法
def eat
// 具体成员
var age: Int = 0
// 具体方法
def sleep: Unit = println("sleeping ....")
}
注意:让特质混有具体行为有一个弊端. 当特质改变时, 所有混入该特质的类都必须重新编译
特质动态混入(mixin)
动态混入(mixin):指在创建单个对象时,可以在不破坏对象声明的前提下,扩展对象的功能
在构造单个对象时, 你可以为它添加特质
- 特质可以将对象原本没有的方法与字段加入对象中, 功能扩展
- 无需修改类声明定义,扩展类的功能,灵活简便
- 如果特质和对象改写了同一超类的方法, 则排在右边的先被执行
package traits.mixin
/**
* 特质类 类似于java的接口
*/
trait Animal {
// 抽象属性
var name: String
// 抽象方法
def eat
// 具体成员
var age: Int = 0
// 具体方法
def sleep: Unit = println("sleeping ....")
}
/**
* 普通类
*/
class Person
class SmallStudent extends Person {
}
object SmallStudent {
def main(args: Array[String]): Unit = {
// 创建普通对象时,具备动物基本特征
// 动态混入(mixin)
val s1 = new SmallStudent() with Animal{
override var name: String = _
override def eat: Unit = println("小学生吃辣条...")
}
println(s1.age) // 0
s1.name = "狗蛋"
println(s1.name) // 狗蛋
s1.eat // 小学生吃辣条...
s1.sleep // sleeping ....
}
}
this别名
scala中this
代表的是当前类,可以给this
起别名,通常命名为self
package traits
class Cat {
// this别名语法
self =>
var name:String = _
def this(name:String){
this()
// this.name = name
self.name = name
}
println(this == self)
}
object Cat{
def main(args: Array[String]): Unit = {
val cat = new Cat()
}
}
外部类和内部类的应用
class Outer {
outer =>
val v1 = "here"
class Inner {
inner =>
val v1 = "-------------"
println(outer.v1) // 用outer表示外部类,相当于Outer.this
println(inner.v1)
}
}
object Outer {
def main(args: Array[String]): Unit = {
val outer = new Outer()
val inner = new outer.Inner
/**
* here
* -------------
*/
}
}
self-type(自类型)
强制混入: 类在声明时需要混入特质类或者抽象类
package traits
trait Fruit {
var name: String
}
trait Apple {
// 强制混入Fruit特质类
my: Fruit =>
def eat= println(my.name)
}
class RedApple extends Apple with Fruit{
override var name: String = "红苹果"
}
object RedApple{
def main(args: Array[String]): Unit = {
new RedApple().eat
}
}
应用程序对象
Java中,每一个程序都需要从一个对象的main 方法开始,Scala中也同样,每一个程序都必须从一个对象的main 方法开始,这个方法的类型为Array[String]。Java中可以使用Junit 测试方法,Scala中有一个类似的特质类,实现类似的功能
App 特质类扩展自另一个特质类DelayedInit
,有该特质的类其初始化方法都会被挪到delayedInit方法中,App特质的main方法捕获到命令行参数,调用delayedInit方法,并且还可以根据要求打印出程序执行所用的时间
package function
import scala.util.Properties
object HighOrderFunction3 extends App {
println(args.length)
var arr = Array[String]("Hello Hadoop","Hello Kafka")
//显示程序执行时间 注意导包
Properties.setProp("scala.time","true")
arr
.flatMap(_.split("\\s"))
.filterNot(_.equalsIgnoreCase("kafka"))
.map((_,1L))
.groupBy(_._1)
.map(t2 => (t2._1,t2._2.length))
.foreach(println)
}