zoukankan      html  css  js  c++  java
  • Scala学习笔记特质trait

    http://outofmemory.cn/scala/scala-trait-introduce-and-example

    与Java相似之处

    Scala类型系统的基础部分是与Java非常相像的。Scala与Java一样有单一的根类,Java通过接口来实现多重继承,而Scala则通过特征(trait)来实现(Scala的特征可以包含实现代码,这当然是与Java接口不同的。不过由于特征自己具有类型的功能,所以对于没有包含实现代码的特征,可以认为与Java的接口是等价的)
    用Trait来实现混入(mix-in)式的多重继承
    Scala里相当于Java接口的是Trait(特征)。Trait的英文意思是特质和性状(本文称其为特征),实际上他比接口还功能强大。与接口不同的是,它还可以定义属性和方法的实现。Scala中特征被用于服务于单一目的功能模块的模块化中。通过混合这种特征(模块)群来实现各种应用程序的功能要求,Scala也是按照这个构想来设计的。
    一般情况下Scala的类只能够继承单一父类,但是如果是特征的话就可以继承多个,从结果来看就是实现了多重继承。就看一下下面的例子吧。为了辨认方便,此后的特征名称前都加上前缀字母T。特征既可以继承类也可以继承其他特征。


    特质的定义除了使用关键字trait以外,与类定义无异
    我们再看下Flyable和Swimable两个 trait的实现:

    trait Flyable {     //特质1
        def hasFeather = true
        def fly
    }
    
    trait Swimable {     //特质2
        def swim
    }

    注意Flyable trait中有两个方法,一个是hasFeather方法,这个方法已经实现了,另一个方法是fly方法,这个方法只是定义没有实现,而Swimable trait只是定义个一个swim的方法,没有具体实现。
    一旦特质被定义,就可以使用extends或with关键字,把它混入类中。Scala程序员“混入”特质而不是继承它们,因为“混入”与多重继承有明显差异

    (1)用extends混入Flyable特质的类,
    这种情况下隐式继承了特质的超类。就下面的例子来说,Bird类是AnyRef(AnyRef是Flyable的超类)的子类,并混入了Flyable特质。

    class Bird extends Flyable{
        def fly()=println("Bird can fly!")
    }

    特质同样也是类型,可以这么用:

    val flyStyle1 : Flyable = new Bird;

    val flyStyle2 : Flyable = new Flyable; // 错误的用法

    (2)如果想把特质混入显式扩展超类的类里,可以用extends指明待扩展的超类,用with混入特质

    我们先定义一个Aminmal类:

    abstract class Animal {
        def walk(speed:Int)   //抽象方法
    
        def breathe() = {
            println("animal breathes")
        }
    }    

     这里的抽象类Animal定义了walk方法,实现了breathe方法。

    下面我们定义一种动物,它既会飞也会游泳,这种动物是鱼鹰 FishEagle,我们看下代码:

    class FishEagle extends Animal with Flyable with Swimable {
      def walk(speed:Int) = println("fish eagle walk with speed " + speed)
      def swim() = println("fish eagle swim fast")
      def fly() = println("fish eagle fly fast")
    }

    FishEagle类继承自Animal,extends Animal后面有两个with,with Flyable和with Swimable,表示也具备两种特征。

    在类的实现中需要实现抽象类Animal的walk方法,也需要实现两个特征中定义的未实现方法。

    特质类似于带有具体方法的Java接口,不过特质能做更多的事情。
    例如,特质可以声明字段和维持状态值。实际上,你可以用特质的定义做任何用类定义能做的事,并且除了以下两点以外连语法都是一样的。
    第一点,特质不能有任何“类”参数,即传递给类的主构造器的参数。
    eg

    class Point(x:Int,y:Int) //正确
    trait NoPoint(x:Int,y:Int)//不能编译通过

    第二点,不论在类的哪个地方,super调用都是静态绑定的,而在特质中,他们是动态绑定的。
    如果在类中写下“super.toString”,你很明确哪个方法实现将被调用。
    然而如果在特质中写了同样的东西,在你定义特质的时候super调用的方法实现尚未被定义。调用的实现将在每一次特质被混入到具体类的时候才被决定。
    这种处理super的有趣行为是使得特质能以可堆叠的改变方式工作的关键

     

  • 相关阅读:
    Microsoft Enterprise Library 5.0 系列(二) Cryptography Application Block (初级)
    Microsoft Enterprise Library 5.0 系列(五) Data Access Application Block
    Microsoft Enterprise Library 5.0 系列(八) Unity Dependency Injection and Interception
    Microsoft Enterprise Library 5.0 系列(九) Policy Injection Application Block
    Microsoft Enterprise Library 5.0 系列(三) Validation Application Block (高级)
    软件研发打油诗祝大家节日快乐
    从挖井的故事中想到开发管理中最容易忽视的几个简单道理
    ITIL管理思想的执行工具发布
    管理类软件设计“渔”之演化
    20070926日下午工作流与ITILQQ群 事件管理 讨论聊天记录
  • 原文地址:https://www.cnblogs.com/gnivor/p/4251139.html
Copyright © 2011-2022 走看看