Scala学习整理[第十一-十三章 类型/特质和其应用/包]<Programming In Scala>

第十一章 类型结构

  • Any

    • 公共基类 ,定义了基本的equals(==/!=的实现)/##(hashCode)/toString等方法
  • AnyVal

    • 所有内建类型的父类 ,Byte,Short,Char,Int,Long,Float,Double,Boolean(对应JAVA基本类型),Unit(void)
      类型间使用隐式转换 ,用implicit声明一个转换函数并import到目标点 ,遇到类型不匹配会调用相关的转换函数
  • AnyRef

    • 所有引用类型的基类 ,类似于Java中的java.lang.Object
  • Null Nothing

    • 底层类型
    • Null表示null引用(AnyRef的子类)
    • Nothing是Null的子类 ,没有任何实例 ,通常在程序的非正常中止时作为”无”的返回值
def divide(x:Int,y:Int):Int=
if(y!=0) x/y
else error("Cannot divide by Zero")

def error(message:String) :Nothing =
throw new RuntimeException(message)

如果在Java中你需要在错误时候返回一个默认结果 ,因为函数需要返回Int
这里则可以直接返回Nothing(子类) ,并由外界函数检查

第十二章 特质(类似接口 ,应用更广和复杂)

package SecondWithProgrammingInScala


package Zoo {


  import scala.io.StdIn

  /**
    * trait 特质
    * 是重用代码的一个基本单位 用于封装方法和变量
    * 类似于Java的接口 可以继承多个trait(只能继承一个class) 可以有实现
    * =java的 interface+abstract class
    *
    * 使用一个动物园来描述 继承和特质
    * 组合是have-a  继承是is-a
    */

  //可以用trait做大多数事 包括设置字段和状态值
  //但是无法像类一样创建构造参数
  //因此scala倾向于胖接口设计 因为在接口上可以进行处理 可以减少实现者的压力
  //同时调用者可以从胖接口的多种方法上获利
  abstract class Animal {
    def bark: Unit
  }

  trait Body {
    def body: String
  }

  trait Color {
    private val defaultColor = Array("红", "橙", "黄", "绿", "青", "蓝", "紫")

    def color: String = {
      defaultColor((new util.Random).nextInt(defaultColor.length))
    }
  }

  /**
    * 从下面例子可见
    * 1.abstract只能继承一个 ,trait特质可以有多个(with连接)
    * 2.trait特质也可以设置内部变量 ,可以设置使用范围(private只能在特质内)
    * 3.应用胖接口设计 ,对一些接口可以在特质中提前实现 ,不必交给使用者(相比java的接口)
    */
  class Cat extends Animal with Color with Body {
    println("你抓住了一只" + color + "色的" + body + "猫")

    override def bark: Unit = println("喵喵喵")

    override def body: String = "小"
  }

  class Dog extends Animal with Color with Body {
    println("你抓住了一只" + color + "色的" + body + "狗")

    override def bark: Unit = println("汪汪汪")

    override def body: String = "大"
  }

  class Zoo {
    //private 只能类/对象本身访问
    //protect 类和派生类可访问
    //public 默认权限 公开访问
    private var animalMap: Map[String, Animal] = Map()
    initZoo

    def findAnimal(name: String): Animal = {
      animalMap(name)
    }

    private def initZoo: Unit = {
      //多态
      animalMap += ("dog" -> new Dog)
      animalMap += ("cat" -> new Cat)
    }
  }

  object ZooMgnt {
    def main(args: Array[String]): Unit = {
      val zoo = new Zoo

      var line = ""
      while (true) {
        line = StdIn.readLine()
        try {
          zoo.findAnimal(line.trim.toLowerCase).bark
        } catch {
          case ex: Exception => println("动物园里还没有这种动物")
        }
      }
    }
  }

}

//胖接口应用 : Ordered Trait
//Ordered Trait 接口内部利用compare函数 ,实现了大于小于等其他比较 ,因此用户只需要实现compare函数就可以使用其他比较符号
//override def compare

package Queue {

  import scala.collection.mutable.ArrayBuffer

  /**
    * 使用Trait处理可叠加的修改操作 创建对象时混合trait
    */

  //定义一个队列
  abstract class IntQueue {
    //返回队首
    def get(): Int

    //加入到队尾
    def put(x: Int)
  }

  class BasicIntQueue extends IntQueue {
    private val buf = new ArrayBuffer[Int]

    def get() = buf.remove(0)

    def put(x: Int) {
      buf += x
    }

    def show {
      println(buf)
    }
  }

  //trait继承基类 保证继承trait的只能是基类的子类(具有相同的函数)
  //如果调用的super.put是一个没有实现的抽象函数 那么在重载的函数前面也要加上abstract
  //那么在最后实现的时候 调用的super.put会指向 super->IntQueue->IntQueue子类的put实现
  //否则会去寻找IntQueue的实现
  trait Doubling extends IntQueue {
    //利用trait重载函数
    abstract override def put(x: Int) {
      //重载的函数调用父类函数 => 父类函数被其子类实现 => 调用子类实现
      super.put(2 * x)
    }
  }

  trait Incrementing extends IntQueue {
    abstract override def put(x: Int) {
      super.put(x + 1)
    }
  }

  trait Filtering extends IntQueue {
    abstract override def put(x: Int) {
      if (x >= 0) super.put(x)
    }
  }

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

      val basicQueue = new BasicIntQueue
      val doubleQueue = new BasicIntQueue with Doubling
      val incrementQueue = new BasicIntQueue with Incrementing
      val filterQueue = new BasicIntQueue with Filtering

      Array(10, 2, 33, -21, -1, 4, -3).foreach(e => {
        basicQueue.put(e)
        doubleQueue.put(e)
        incrementQueue.put(e)
        filterQueue.put(e)
      })

      Array(basicQueue, doubleQueue, incrementQueue, filterQueue).foreach(e => {
        e.show
      })
    }
  }
}

第十三章 包和引用

在之前的代码中已经有所体现 ,包和引用的规则与Java也比较类似 .作用域有更详细的控制方法 .(注意代码中的包名)

package SecondWithProgrammingInScala.Package

/**
  * 包和引用
  * 之前的代码中已经展示过
  * 在scala中 ,可以在同一个文件中定义多个包 ,并且设置各自包内的类的访问权限
  * import也可以在任意地方使用 ,并且像局部变量 ,有着应用域
  */

//在文件中还可以定义package用来分隔文件
package navigation {

  import SecondWithProgrammingInScala.Package.navigation

  //private[x]  protect[x]
  // x可以是包/对象/类 表示允许访问的范围
  private[Package] class Navigator {

    protected[navigation] def useStarChart() {}

    //内部类
    class LegOfJourney {
      private[Navigator] val distance = 100
    }


    private[this] var speed = 200

    def demo: Unit = {
      val other = new Navigator
      // private[this] 只在创建该实例中可用 这里使用了new 外界无法读取
      //other.speed

      val leg = new LegOfJourney
      val dis = leg.distance
    }
  }

  class NavDemo {
    val navigator = new Navigator
    navigator.useStarChart()

    //使用内部类
    val leg = new navigator.LegOfJourney
    //distance是Navigator类下可访问
    //val dis = leg.distance
  }

}

package Launch {
  //引入包
  import FirstInShiyanlou.Package.Launch
  import navigation._

  object Vehicle {
    //Navigator是Package包下可访问
    private[Launch] val guide = new Navigator

    //useStarChart是Navigation包下可访问
    //guide.useStarChart //error

    //使用内部类
    val leg = new guide.LegOfJourney
    //distance是Navigation包下可访问
    //val dis = leg.distance  //error
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值