1、抽象类 和java中一样 定义抽象类需要使用abstract
object AbstractScala {
def main(args: Array[String]): Unit = {
val cat = new Cat("小小")
cat.cry
}
}
abstract class Animal(name:String){
var kind:String //抽象field
def cry //抽象方法
}
class Cat(name:String) extends Animal(name){
override var kind: String = "猫"
override def cry: Unit = println(kind + "["+name+"]" + ":喵!!")
}
2、trait和java中有很大区别 java中接口方法是不能有具体的实现,同时接口也不能继承类,而scala的trait是能有具体实现也能继承类
/**
* 继承这个trait就必须实现其中的抽象方法
*/
trait Logger{
/**
* Scala中的Triat可以定义具体field,此时继承trait的类就自动获得了trait中定义的field
* 但是这种获取field的方式与继承class是不同的:如果是继承class获取的field,
* 实际是定义在父类中的;而继承trait获取的field,就直接被添加到了类中
*/
val time:Long = new Date().getTime
val method:String //抽象字段 类在继承此trait时必须覆盖抽象time字段,提供具体的值
/**
* 抽象方法 类似接口
* @param msg
*/
def info(msg:String)
/**
* 具体的函数实现 所以如果需要重写 那么必须要加override修饰
* @param msg
*/
def error(msg:String) = {}
}
trait ImpLogger extends Logger{
override def error(msg: String) = println(time+"->>>"+method+"->>>"+msg)
}
/**
* 我们把类继承了trait都叫做 类混入trait
* 在这里强调一定 java里面用implement来实现接口,scala里面只有extends 如果使用多个trait,extends后使用with
*/
class ConCreateLogger(m:String) extends Logger with Cloneable{
val method: String = m //实现父类的抽象field
def info(msg: String): Unit = println(time+"->>>"+method+"->>>"+msg)
}
objectTraitScala {
def main(args: Array[String]): Unit = {
val log = new ConCreateLogger("hello")
log.info("test")
log.error("sss")
/**
* 在创建对象的时候混入特质
* 前提:ImpLogger必须必须和ConcreateLogger一样继承于Logger,这样才能覆盖混入
*/
val log2 = new ConCreateLogger("say") with ImpLogger
log2.error("kk")
}
}
输出结果:
1482373668400->>>hello->>>test
1482373668668->>>say->>>kk
3、trait调用链以及继承多个trait的构造顺序
/**
* 下面是测试类继承多个trait的构造顺序 同时trait也可以继承class
*/
class Animals {println("Animal is init")}
trait Furry extends Animals {println("Furry is init")}
trait HasLegs extends Animals {println("HasLegs is init")}
trait FourLegged extends HasLegs {println("FourLegged is init")}
/**
* 继承了trait的类的构造机制如下
* 1、父类的构造函数执行;
* 2、trait的构造代码执行,多个trait从左到右依次执行;
* 3、构造trait时会先构造父trait,如果多个trait继承同一个父trait,则父trait只会构造一次;
* 4、所有trait构造完毕之后,子类的构造函数执行
*/
class Dog extends Animals with Furry with FourLegged{
println("Cat is init")
}
trait Handler{
def handler(data:String){}
}
trait DataHandler extends Handler{
override def handler(data:String): Unit = {
println("data check" + data)
super.handler(data)
}
}
trait SignatureHandler extends Handler{
override def handler(data:String): Unit = {
println("signature check" + data)
super.handler(data)
}
}
/**
* trait 调用链 从右向左
* @param name
*/
class User(name:String) extends Handler with SignatureHandler with DataHandler{
def sayHello() = {
println("hello "+name)
handler(name)
}
}
object TraitScala {
def main(args: Array[String]): Unit = {
val cat = new Dog
println(cat)
val u = new User("tom")
u.sayHello
}
}
输出结果:
Animal is init
Furry is init
HasLegs is init
FourLegged is init
Cat is init
com.aralbox.Dog@1ae369b7
hello tom
data checktom
signature checktom
4、基于trait的AOP实战
/**
* 下面这个例子基于trait的AOP代码实战
* 也就是基于trait 调用链方式
*/
trait DoAction {
def action
}
trait AopBefore extends DoAction{
/**
* 在trait中,是可以覆盖父trait的抽象方法
* 但是如果方法体使用了super.方法的代码,则无法通过编译
* 因为super.方法就会去掉用父trait的抽象方法,此时子trait的该方法还是会被认为是抽象的
* 此时如果要通过编译,就得给子trait的方法加上abstract override修饰
*/
abstract override def action = {
println("调用前执行-----------")
super.action
println("调用后执行-------------")
}
}
class Work extends DoAction{
override def action: Unit = println("Work!")
}
object TraitScala {
def main(args: Array[String]): Unit = {
//其实就是使用了trait调用链的特性
val w = new Work with AopBefore
w.action
}
}
输出结果:
调用前执行-----------
Work!
调用后执行-------------