1、将trait作为接口使用

  • Scala中的trait是一种特殊的概念;
  • 首先先将trait作为接口使用,此时的trait就与Java中的接口 (interface)非常类似;
  • 在trait中可以定义抽象方法,就像抽象类中的抽象方法一样,只要不给出方法的方法体即可;
  • 类可以使用extends关键字继承trait,注意,这里不是 implement,而是extends ,在Scala中没有 implement 的概念,无论继承类还是trait,统一都是 extends;
  • 类继承后,必须实现其中的抽象方法,实现时,不需要使用 override 关键字;
  • Scala不支持对类进行多继承,但是支持多重继承 trait,使用 with 关键字即可。

    举例说明:

          
 

        trait HelloTrait {

          def sayHello(): Unit

        }

        trait MakeFriendsTrait {

          def makeFriends(c: Children): Unit

        }

        //多重继承 trait

        class Children(val name: String) extends HelloTrait with MakeFriendsTrait with Cloneable with Serializable{

          def sayHello() =println("Hello, " + this.name)

          def makeFriends(c: Children) = println("Hello, my name is " + this.name + ", your name is " + c.name)

        }

        object Children{

          def main(args: Array[String]) {

            val c1=new Children("tom")

            val c2=new Children("jim")

            c1.sayHello()//Hello, tom

            c1.makeFriends(c2)//Hello, my name is tom, your name is jim

          }

        }

 
 

2、在trait中定义具体的方法

  • Scala中的trait不仅可以定义抽象方法,还可以定义具体的方法,此时 trait 更像是包含了通用方法的工具,可以认为trait还包含了类的功能。

    举例说明:

    /**

     * 比如 trait 中可以包含很多子类都通用的方法,例如打印日志或其他工具方法等等。

     * spark就使用trait定义了通用的日志打印方法;

     */

    trait Logger {

      def log(message: String): Unit = println(message)

    }

    class PersonForLog(val name: String) extends Logger {

      def makeFriends(other: PersonForLog) = {

        println("Hello, " + other.name + "! My name is " + this.name + ", I miss you!!")

        this.log("makeFriends method is invoked with parameter PersonForLog[name = " + other.name + "]")

      }

    }

    object PersonForLog{

      def main(args: Array[String]) {

        val p1=new PersonForLog("jack")

        val p2=new PersonForLog("rose")

        p1.makeFriends(p2)

        //Hello, rose! My name is jack, I miss you!!

        //makeFriens method is invoked with parameter PersonForLog[name = rose]

      }

    }

 
 

3、在trait中定义具体field

  • Scala 中的 trait 可以定义具体的 field,此时继承 trait 的子类就自动获得了 trait 中定义的 field;
  • 但是这种获取 field 的方式与继承 class 的是不同的。 如果是继承 class 获取的 field ,实际上还是定义在父类中的;而继承 trait获取的 field,就直接被添加到子类中了。

    举例说明:

        
 

        trait PersonForField {

          val  age:Int=50

        }

        
 

        //继承 trait 获取的field直接被添加到子类中

        class StudentForField(val name: String) extends PersonForField {

          def sayHello = println("Hi, I'm " + this.name + ", my  age  is "+ age)

        }

        
 

        object StudentForField{

          def main(args: Array[String]) {

            val s=new StudentForField("tom")

            s.sayHello

          }

 
 

}

4、在trait中定义抽象field

  • Scala中的trait也能定义抽象field, 而trait中的具体方法也能基于抽象field编写;
  • 继承trait的类,则必须覆盖抽象field,提供具体的值;

    举例说明:

 
 

    trait SayHelloTrait {

      val msg:String

      def sayHello(name: St

    ring) = println(msg + ", " + name)

    }

    
 

    class PersonForAbstractField(val name: String) extends SayHelloTrait {

      //必须覆盖抽象 field

      val msg = "Hello"

      def makeFriends(other: PersonForAbstractField) = {

        this.sayHello(other.name)

        println("I'm " + this.name + ", I want to make friends with you!!")

      }

    }

    object PersonForAbstractField{

      def main(args: Array[String]) {

        val p1=new PersonForAbstractField("Tom")

        val p2=new PersonForAbstractField("Rose")

        p1.makeFriends(p2)

      }

    }

 
 

5、在实例对象指定混入某个trait

  • 可在创建类的对象时,为该对象指定混入某个trait,且只有混入了trait的对象才具有trait中的方法,而其他该类的对象则没有;
  • 在创建对象时,使用 with 关键字指定混入某个 trait;

    举例说明:

    trait LoggedTrait {

      // 该方法为实现的具体方法

      def log(msg: String) = {}

    }

    trait MyLogger extends LoggedTrait{

      // 覆盖 log() 方法

    override def log(msg: String) = println("log: " + msg)

    }

    
 

    class PersonForMixTraitMethod(val name: String) extends LoggedTrait {

      def sayHello = {

        println("Hi, I'm " + this.name)

        log("sayHello method is invoked!")

      }

    }

    object PersonForMixTraitMethod{

      def main(args: Array[String]) {

        val tom= new PersonForMixTraitMethod("Tom").sayHello //结果为:Hi, I'm Tom

        // 使用 with 关键字,指定混入MyLogger trait

        val rose = new PersonForMixTraitMethod("Rose") with MyLogger

        rose.sayHello

    // 结果为:     Hi, I'm Rose

    // 结果为:     log: sayHello method is invoked!

      }

    }

6、trait 调用链

  • Scala中支持让类继承多个trait后,可依次调用多个trait中的同一个方法,只要让多个trait中的同一个方法,在最后都依次执行 super 关键字即可;
  • 类中调用多个trait中都有的这个方法时,首先会从最右边的trait的方法开始执行,然后依次往左执行,形成一个调用链条;
  • 这种特性非常强大,其实就是设计模式中责任链模式的一种具体实现;

    案例说明:

    trait HandlerTrait {

      def handle(data: String) = {println("last one")}

    }

    trait DataValidHandlerTrait extends HandlerTrait {

      override def handle(data: String) = {

                  println("check data: " + data)

                  super.handle(data)

    }

    }

    trait SignatureValidHandlerTrait extends HandlerTrait {

      override def handle(data: String) = {

              println("check signature: " + data)

              super.handle(data)

      }

    }

    class PersonForRespLine(val name: String) extends SignatureValidHandlerTrait with DataValidHandlerTrait {

      def sayHello = {

            println("Hello, " + this.name)

            this.handle(this.name)

      }

    }

    object PersonForRespLine{

      def main(args: Array[String]) {

         val p=new PersonForRespLine("tom")

          p.sayHello

          //执行结果:

    //    Hello, tom

    //    check data: tom

    //    check signature: tom

    //    last one

      }

    }

7、混合使用 trait 的具体方法和抽象方法

  • 在 trait 中,可以混合使用具体方法和抽象方法;
  • 可以让具体方法依赖于抽象方法,而抽象方法则可放到继承 trait的子类中去实现;
  • 这种 trait 特性,其实就是设计模式中的模板设计模式的体现;

    举例说明:

    trait ValidTrait {

     //抽象方法

      def getName: String    

    //具体方法,具体方法的返回值依赖于抽象方法

                            
 

     def valid: Boolean = {"Tom".equals(this.getName)

      }

    }

    class PersonForValid(val name: String) extends ValidTrait {

      def getName: String = this.name

    }

    
 

    object PersonForValid{

      def main(args: Array[String]): Unit = {

        val person = new PersonForValid("Rose")

        println(person.valid)

      }

    }

 
 

 
 

8、trait的构造机制

  • 在Scala中,trait也是有构造代码的,即在trait中,不包含在任何方法中的代码;
  • 继承了trait的子类,其构造机制如下:
  • 父类的构造函数先执行, class 类必须放在最左边;多个trait从左向右依次执行;构造trait时,先构造父 trait,如果多个trait继承同一个父trait,则父trait只会构造一次;所有trait构造完毕之后,子类的构造函数最后执行。

    举例说明:

        class Person_One {

          println("Person's constructor!")

        }

        trait Logger_One {

          println("Logger's constructor!")

        }

        trait MyLogger_One extends Logger_One {

          println("MyLogger's constructor!")

        }

        trait TimeLogger_One extends Logger_One {

          println("TimeLogger's contructor!")

        }

        class Student_One extends Person_One with MyLogger_One with TimeLogger_One {

          println("Student's constructor!")

          }

        object exe_one {

          def main(args: Array[String]): Unit = {

            val student = new Student_One

            //执行结果为:

        //      Person's constructor!

        //      Logger's constructor!

        //      MyLogger's constructor!

        //      TimeLogger's contructor!

        //      Student's constructor!

          }

        }

 
 

9、trait 继承 class

  • 在Scala中trait 也可以继承 class,此时这个 class 就会成为所有继承该 trait 的子类的超级父类。

    举例说明:

        class MyUtil {

          def printMsg(msg: String) = println(msg)

        }

        trait Logger_Two extends MyUtil {

          def log(msg: String) = this.printMsg("log: " + msg)

        }

        class Person_Three(val name: String) extends Logger_Two {

            def sayHello {

                this.log("Hi, I'm " + this.name)

                this.printMsg("Hello, I'm " + this.name)

          }

        }

        object Person_Three{

          def main(args: Array[String]) {

              val p=new Person_Three("Tom")

              p.sayHello

            //执行结果:

        //      log: Hi, I'm Tom

        //      Hello, I'm Tom

          }

        }

 

scala当中的特质trait的更多相关文章

  1. Scala学习笔记--特质trait

    http://outofmemory.cn/scala/scala-trait-introduce-and-example 与Java相似之处 Scala类型系统的基础部分是与Java非常相像的.Sc ...

  2. Scala学习十——特质

    一.本章要点 类可以实现任意数量的特质 特质可以要求实现它们的类具备特定的字段,方法或超类 和Java接口不同,Scala特质可以提供方法和字段实现 当你将多个特质叠加在一起时,顺序很重要——其方法先 ...

  3. scala当中的类型参数

    类型参数主要就是研究scala当中的类或者scala当中的方法的泛型 1.scala当中的类的泛型         object Demo8 {          def main(args: Arr ...

  4. scala当中的对象

    1.scala当中的Object 在scala当中,没有类似于像java当中的static修饰的静态属性或者静态方法或者静态代码块之类的,但是我们可以通过scala当中的Object来实现类似的功能. ...

  5. scala当中的文件操作和网络请求

    1.读取文件当中每一行的数据 def main(args: Array[String]): Unit = { //注意文件的编码格式,如果编码格式不对,那么读取报错 val file: Buffere ...

  6. scala当中的类

    1.类的定义与创建 创建一个scala class来定义我们的一个类.类当中可以定义各种属性或者方法,或者函数都可以     class Person {       //定义一个属性,叫做name的 ...

  7. scala当中的Actor并发编程

    注:Scala Actor是scala 2.10.x版本及以前版本的Actor. Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃. 1.什么是Sc ...

  8. scala学习手记31 - Trait

    不知道大家对java的接口是如何理解的.在我刚接触到接口这个概念的时候,我将接口理解为一系列规则的集合,认为接口是对类的行为的规范.现在想来,将接口理解为是对类的规范多少有些偏颇,更恰当些的观点应该是 ...

  9. Beginning Scala study note(7) Trait

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

随机推荐

  1. C语言读写配置文件--转载

    http://www.oschina.net/code/snippet_4873_2503 [].[代码] CException.h 跳至 [] [] [] /******************** ...

  2. ASP.NET MVC Core的ViewComponent

    MVC Core新增了ViewComponent的概念,直接强行理解为视图组件,用于在页面上显示可重用的内容,这部分内容包括逻辑和展示内容,而且定义为组件那么其必定是可以独立存在并且是高度可重用的. ...

  3. SQL语句的增删改查(详细)

    摘录自:http://blog.csdn.net/a88055517/article/details/6736284 一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [in ...

  4. 转:详解PV、UV、VV、IP及其关系与计算

    一.什么是PV? PV即Page View,网站浏览量,指页面浏览的次数,用以衡量网站用户访问的网页数量.用户每次打开一个页面便记录1次PV,多次打开同一页面则浏览量累计.一般来说,PV与来访者的数量 ...

  5. Sublime Text - 在浏览器打开当前文件

    有没有办法通过快捷键在指定的浏览器中打开当前文件? 有点怀念Dreamweaver的F12? 其实Sublime也可以实现这一效果,而且不需要安装任何插件. 进入Tools -> Build S ...

  6. 撩课-Python-每天5道面试题-第5天

    一. 给定一个圆心和半径, 以及一个点坐标, 判定该点是否在圆内; 例如: 用户输入圆心: (1, 2) 半径: 2.5 测试点为(2, 2)结果: 判定测试点是在圆内 思路: 结合勾股定理, 计算测 ...

  7. 系统分析与设计 homework-1

    1.软件工程的定义 软件工程是将系统化.规范化.可度量的方法应用于软件的开发.运营和维护上,也就是将工程方法应用于软件上,并对这些方法的研究. 2.软件危机(software crisis) 软件危机 ...

  8. jetbrains激活 webstorm激活 webstorm激活码

    License Activation的破解方式无效时,请采用以下方法1. 把下载的破解补丁放在你的idea的安装目录下的bin的目录下面(如下图所示),本文示例为C:\Program Files\Je ...

  9. Java注解拾遗

    注解简介: 注解Annotation是jdk1.5的新增功能,在现在的日常开发中,几乎离不开注解,写篇短文,来做个拾遗. 注解作用: Annotation(注解)的作用是修饰包.类.构造方法.方法.成 ...

  10. js比较好的一些方法

    js里面有些方法比较容易忘记,但却很实用,很好用的一些方法.在此记录: 1.Math.ceil(x) — 返回大于等于数字参数的最小整数(取整函数),对数字进行上舍入 2.Math.floor(x)– ...