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的有趣行为是使得特质能以可堆叠的改变方式工作的关键

     

  • 相关阅读:
    k8s 权限控制初探
    golang gRPC 入门
    gpushare-scheduler-extender 升级依赖引发关于 golang dep 工具的思考
    admission webhook 初探(编译篇)
    以 gpushare-device-plugin 为例,探究 Resource yaml 配置
    编译 gpushare-device-plugin
    浅谈 docker 挂载 GPU 原理
    CCF计算机职业资格认证考试题解
    优达学城机器学习工程师纳米学位项目介绍
    IEEEXtreme 极限编程大赛题解
  • 原文地址:https://www.cnblogs.com/gnivor/p/4251139.html
Copyright © 2011-2022 走看看