三、Scala的常用数据类型
    1、注意:在Scala中,任何数据都是对象。
        举例:数字 1 ----> 是一个对象,就有方法
        scala> 1.toString
        res0: String = 1     ----> 定义了新的变量 res0,类型String
        
    2、Scala定义变量的时候,可以不指定变量的类型,Scala会进行类型的自动推导
        举例:下面的语句是一样的
              var a:Int = 10
              var b = 10
              
        如何定义常量? val
              val c = 10
        
    3、数据的类型
        (1)数值类型:复习
            (*)Byte:  8位的有符号   -128~127
            (*)Short:16位的有符号   -32768 ~ 32767
            (*)Int:   32位的有符号
            (*)Long: 64位的有符号
            (*)Float:浮点数
            (*)Double:双精度
        
        (2)字符串:Char、String
             对于字符串,在Scala中可以进行插值操作
             val s1 = "hello world"
             
             可以在另一个字符串中,引用s1的值
             s"My name is Tom and ${s1}"
        
        (3)Unit类型:相当于Java中的void 类型
                ()代表一个函数:没有参数,也没有返回值
        
                scala> val f = ()
                f: Unit = ()
                
                val f = (a:Int)
        
        (4)Nothing类型:一般来说,表示在函数(方法)执行过程中产生了Exception
            举例: 定义函数 def
                   def myfunction = throw new Exception("some exception ....")
                   myfunction: Nothing
        
四、Scala的函数    
    1、内置函数:数***算
        举例:求最大值
        max(1,2)
        
        包: import scala.math._
        https://www.scala-lang.org/files/archive/api/2.11.8/#package
        
        scala> max(1,2)
        res4: Int = 2  ----> 定义了一个新的变量来保存运算的结果
        
        var result:Int = max(1,2)
        var result = max(1,2)
    
    2、自定义函数:def
        
        
    3、Scala的条件表达式 if.. else
        //注意:scala中函数的最后一句话,就是函数分返回值
        //不写reture        
        
五、循环: for、while、do...while

六、Scala函数的参数:求值策略
    1、call by value:对函数的实参求值,并且仅求一次
        举例:def test1(x:Int,y:Int):Int = x+x  没有用到y     
    2、call by name:函数的实参每次在函数体内部被调用的时候,都会进行求值
        举例:def test2(x: => Int,y: =>Int):Int = x+x  没有用到y
        

    3、一个复杂点的例子
        x是call by value
        y是call by name
        
       def test3(x:Int,y: =>Int):Int = 1
       
       再定义一个死循环的函数
       def loop():Int = loop
       
       考虑下面的两个调用
       test3(1,loop) ---> 正常
       test3(loop,1) ---> 死循环
       
    4、函数的参数:默认参数、代名参数、可变参数

七、lazy值:如果一个变量被lazy修饰了,他的初始化会被推迟到第一次使用的时候
    举例1
        scala> var x = 10
        x: Int = 10

        scala> lazy val y = x + 10
        y: Int = <lazy>

        scala> y
        res0: Int = 20    
        
    举例2:读文件(存在)
           读文件(不存在)
            scala> val words = scala.io.Source.fromFile("d:\\temp\\a.txt").mkString
            words: String = I love Beijing

            scala> val words1 = scala.io.Source.fromFile("d:\\temp\\b.txt").mkString
            java.io.FileNotFoundException: d:\temp\b.txt (系统找不到指定的文件。)
              at java.io.FileInputStream.open0(Native Method)
              at java.io.FileInputStream.open(FileInputStream.java:195)
              at java.io.FileInputStream.<init>(FileInputStream.java:138)
              at scala.io.Source$.fromFile(Source.scala:91)
              at scala.io.Source$.fromFile(Source.scala:76)
              at scala.io.Source$.fromFile(Source.scala:54)
              ... 32 elided

            scala> lazy val words1 = scala.io.Source.fromFile("d:\\temp\\b.txt").mkString
            words1: String = <lazy>

            scala> words1
            java.io.FileNotFoundException: d:\temp\b.txt (系统找不到指定的文件。)
              at java.io.FileInputStream.open0(Native Method)
              at java.io.FileInputStream.open(FileInputStream.java:195)
              at java.io.FileInputStream.<init>(FileInputStream.java:138)
              at scala.io.Source$.fromFile(Source.scala:91)
              at scala.io.Source$.fromFile(Source.scala:76)
              at scala.io.Source$.fromFile(Source.scala:54)
              at .words1$lzycompute(<console>:11)
              at .words1(<console>:11)
              ... 32 elided

            scala>

八、异常:Exception
    补充:复习:异常处理的机制 ----> 向上处理异常机制

九、数组、映射、元组
    1、数组:定长数组  Array
             变长数组  ArrayBuffer
             
    2、映射Map、元组Tuple
        
第二章:Scala面向对象:类似Java
    一、复习:面向对象的基本概念
        (*)定义:把数据和操作数据的方法放到一起,作为一个整体(类 class)
        (*)面向对象的特质:
            (1)封装
            (2)继承
            (3)多态
    
    
    二、定义类class
    
    三、属性的get和set方法
    
    四、内部类(嵌套类):在类的内部,又定义了一个类
        举例:创建类,保存学生和学生考试成绩(科目 成绩)
    
    
    五、类的构造器
        1、主构造器:跟类名写在一起,只能有一个主构造器
        2、辅助构造器:可以有个多个,关键字 this 
        
    六、Object对象(相当于Java中的static)
        1、在Object对象中的所有内容都是静态的
        2、举例(1):实现单例模式:一个类只有一个对象
           举例(2):省略main方法,objec对象需要继承App父类

    七、apply方法:作用:使得程序简单,省略new关键字

    八、继承:Scala和Java一样,使用extends关键字扩展类。
        例子:参考讲义
    

    九、特质(trait):当成Java中的抽象类,支持多重继承(像Java的接口)
        trait就是抽象类。trait跟抽象类最大的区别:trait支持多重继承

    十、包和包对象: 参考讲义


第三章:Scala函数式编程(最有特色):核心概念---> 把一个函数作为另一个函数参数的值传递过去
    一、回顾:Scala函数:def关键字
    
    二、什么是匿名函数:没有名字的函数
    
    三、带函数参数的函数:也叫:高阶函数
                          把一个函数作为另一个函数参数的值传递过去
                          一个函数的参数值是另一个函数
                          
    四、闭包、柯里化
    五、示例:常用的高阶函数
        1、map:对集合中的每个元素进行操作,返回一个结果
            val numbers = List(1,2,3,4,5,6)
            每个元素乘以2
            numbers.map((x:Int)=>x*2)
            简写方式
            numbers.map(_*2)
        
        
        2、foreach:对集合中的每个元素进行操作,不返回结果
            numbers.foreach(_*2)
        
        3、filter:过滤,选择满足条件的元素
            选择能够被2整除的元素
            numbers.filter((i:Int)=> i%2==0)
            
            完整
            numbers.filter((i:Int)=>{
                if(i%2 == 0){
                    true
                }else{
                    false
                }
            })
        
        4、zip:把两个集合合并成一个
            List(1,2,3).zip(List(4,5,6))
            
            List(1,2,3).zip(List(4,5,6,7))
        
        5、partition: 分区,根据分区条件,把满足条件的分成一个区,不满足条件的分成另一个区
            val numbers = List(1,2,3,4,5,6)
            能够被2整除的分成一个区,不能整除的分成另一个区
            numbers.partition((i:Int)=> i%2==0)
            
            完整
            numbers.partition((i:Int)=>{
                if(i%2 == 0){
                    true
                }else{
                    false
                }
            })        
                
        6、find: 查找第一个满足条件的元素
            能够被3整除的元素
            numbers.find(_%3 == 0)
        
        
        7、flatten:把一个嵌套的结果展开
            List(List(1,2,3),List(4,5,6)).flatten
                
        8、flatMap = flatten + map
            举例
            val myList = List(List(1,2,3),List(4,5,6))
            myList.flatMap(x=>x.map(_*2))
            
            第一步:将List(1,2,3)和List(4,5,6)展开 (1,2,3,4,5,6)
            第二步:(1,2,3,4,5,6)每个元素乘以2

第四章:Scala常用集合
    一、可变集合、不可变集合
    
    二、列表
    
    三、序列
    
    四、Set:不重复元素的集合,默认是:HashSet
    
    五、模式匹配:就相当于switch ... case 语句
    
    六、样本类:case class,支持模式匹配,就相当于支持switch ... case 语句   相当于 instanceof


第五章:Scala的高级内容:泛型
    一、泛型类:定义类的时候,接收一个泛型参数
    
    二、泛型函数:定义函数的时候,接收一个泛型参数
        举例:
            (1)定义函数:创建一个Int类型的数组
                def mkIntArray(elem:Int*) = Array[Int](elem:_*)
                mkIntArray(1,2,3)
                mkIntArray(1,2,3,4,5)
                
            (2)定义函数:创建一个String类型的数组
                def mkStringArray(elem:String*) = Array[String](elem:_*)
                mkStringArray("Tom","Mary")
                
            (3)在函数中使用泛型,取代上面的两个函数
                import scala.reflect.ClassTag
                def mkArray[T:ClassTag](elem:T*)=Array[T](elem:_*)
                
                说明:ClassTag表示Scala在运行时候的状态信息,这里表示调用时候的数据类型
                
                调用
                mkArray(1,2,3,4,5)
                mkArray("Tom","Mary")
    
    三、泛型的上界和泛型的下界:规定泛型的取值范围
        1、普通的数据类型为例
                  10 <= x:Int <=100  ----> 规定了x的范围(10,100)
                  
        2、规定:类型的取值范围 ---> 下界  上界
                定义几个类(继承关系)  Class A ---> Class B ---> Class C  ---> Class D
                
                定义泛型
                    D  <: T 泛型类型 <: B    ---->  泛型T的取值:B、C、D
        
        3、概念
            上界:定义 S <: T 表示S的类型必须是T的子类
            下界:定义 U >: T 表示U的类型必须是T的父类
            
        4、举例:上界为例
        5、举例:拼加字符,接收类型必须是String或者String的子类
                 def addTwoString[T<:String](x:T,y:T) = {println(x+"*****"+y)}
                 
                 调用
                   addTwoString("abc","xyz")  ---> abc*****xyz
                   addTwoString(100,200)      ---> 期望:100*****200
                    错误
            <console>:13: error: inferred type arguments [Int] do not conform to method addTwoString's type parameter bounds [T <
                   addTwoString(100,200)
                   ^
            <console>:13: error: type mismatch;
             found   : Int(100)
             required: T
                   addTwoString(100,200)
                                ^
            <console>:13: error: type mismatch;
             found   : Int(200)
             required: T
                   addTwoString(100,200)                    

                实际上:addTwoString(100,200) 
                        1、首先 100和200 转换成字符串 "100" "200"
                        2、再拼加 100*****200
        
                                
    四、视图界定: 扩展了上界和下界的范围,表示方式:<% 
        1、可以接收:(1)上界和下界的类型
                     (2)允许接收通过隐式转换过去的类型
                     
                实际上:addTwoString(100,200) 
                        1、首先 100和200 转换(隐式转换)成字符串 "100" "200"
                        2、再拼加 100*****200
                        
        2、改写上面的例子         
            (*)定义订转换规则:隐式转换函数
                    implicit def intToString(n:Int):String = {n.toString}
                    
            (*)使用视图界定改写 addTwoString
                    def addTwoString[T <% String](x:T,y:T) = {println(x+"*****"+y)}
                    表示:T可以是String和String的子类
                            也可以是能够转换成String的其他类型
                            
                            
            (*)分析一下执行的过程
                    addTwoString(100,200)
                    (1)检查参数的类型:Int类型
                         接收的是String的类型
                         
                    (2)在当前的会话中,查找有没有一个隐式转换函数:Int ---> String
                    (3)如果找到,先调用这个隐式转换函数
                         如果没有找到,出错
                         
                    (4)再调用函数
        
    五、协变和逆变
        概念
        1、协变:泛型变量的值可以是本身或者其子类的类型
        
        
        2、逆变:泛型变量的值可以是本身或者其父类的类型
    
    
    六、隐式转换函数:使用关键字implicit
        1、什么是隐式转换函数? 使用关键字implicit,由Scala自动调用
            implicit def intToString(n:Int):String = {n.toString}
            
            
        2、举例:定义一个隐式转换函数,针对class
    
    七、隐式参数:是在参数的前面加上implicit
                用途:实现隐式转换
    
    八、隐式类:是在类的前面加上implicit
                用途:增强类的功能(类似:包装设计模式,动态代理对象)

    
(一两年前:Scala的Actor编程:已经废弃)