Scala学习总结

一、Scala的简介

      Scala是一种基于JVM的编程语言,学习目的主要是为了Spark的学习与相关代码的编写。
    Scala的六大特征:

        1).Java和scala可以无缝混编,都是运行在JVM上的
	2).类型推测(自动推测类型),不用指定类型  
	3).并发和分布式(Actor,类似Java多线程Thread) 
	4).特质trait,特征(类似java中interfaces 和 abstract结合)
	5).模式匹配,match case(类似java switch case)
	6).高阶函数(函数的参数是函数,函数的返回是函数),可进行函数式编程

二、Scala安装使用

  1. windows安装,配置环境变量
  • 官网下载scala2.10:https://www.scala-lang.org/download/2.10.4.html

  • 下载好后安装。双击msi包安装,记住安装的路径。

  • 配置环境变量(和配置jdk一样)
             ①新建SCALA_HOME,配置好Scala安装的目录位置信息。
             ②编辑Path变量,在后面追加如下:
               ;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin

  • 打开cmd,输入:scala - version 看是否显示版本号,确定是否安装成功
    Scala编程语言学习总结

  1. Scala程序编译工具
        ①Scala ide
         下载网址:http://scala-ide.org/download/sdk.html
        ②推荐使用IDEA中配置scala插件
         1》 打开idea项目后,点击Configure->Plugins
    Scala编程语言学习总结     2》搜索scala,点击Install安装
    Scala编程语言学习总结     3》设置jdk,打开Project Structure,点击new 选择安装好的jdk路径
    Scala编程语言学习总结Scala编程语言学习总结     4》创建scala项目,配置scala sdk(Software Development Kit)
    Scala编程语言学习总结

三、Scala基础

1.数据类型
Scala编程语言学习总结Scala编程语言学习总结Scala编程语言学习总结
2.变量和常量的声明
    Scala中通常用var声明变量,可修改;用val声明常量,不可修改即不可对常量进行再赋值;不用指定数据类型,由Scala自己进行类型推测。
注意点: 在scala中每行后面不需要加分号,直接通过换行如来区分;但是一行中写了多个语句,语句与语句之间必须用分号来分割
例如:

var age = 18   ; var name = "angelababy"
    
    var heighat,score = 10
    val sex = "male"

3.类和对象

class :修饰的称为伴生类;定义在class中的属性都是动态的,用于实例化 的;scala中的class类默认可以传参数,默认的传参数就是默认的构造函数。class 类属性自带getter ,setter方法。使用class时要new ,并且new的时候,class中除了方法不执行,其他都执行。

object: 修饰的称为伴生对象;定义在object中的属性(字段、方法)都是静 态的,main函数写在里面;scala 中的object是单例对象,相当于java中的工具类,可以看成是定义静态的方法的类.object不可以传参数。使用object时,不用new.

创建类

class Person{
  val name = "zhangsan"
  val age = 18
  def sayName() = {
    "my name is "+ name
  }
}

    在创建类时,可以在类名后面加入一个括号,括号中写定义的参数类型,括号中的参数就表示类的构造函数由括号内的参数组成。补充: ①当参数用var修饰那么可以通过对象修改其值;当参数用val修饰那么无法通过对象来修改值;当参数没有修饰符,那么在外部无法通过对象来调用。
      ②若想增加一个类的传入参数,则需要在声明的类中重写构造函数,这样就可以在mian函数中声明有增加的属性的对象,当然原来的对象也可以声明。
               重写this函数

  /*
   *  重写的构造函数,参数不能有修饰符
   */
  def this (id:Int,name:String,facePower:Double ){
    //首先要调用父构造函数
    this(id,name)
    fcp = facePower
    
  }

创建对象

object Lesson_Class {
   def main(args: Array[String]): Unit = {
    val person = new Person()
    println(person.age);
    println(person.sayName())
  }
}

Apply方法
       使用此方法时,可以在main函数中不通过new来创建一个对象,即可以不用专门的一次一次地进行实例化,加载创建对象的这个类的时候,会自动调用apply这个方法,类似Java中的static静态块。
       Apply方法的使用用例:

object ScalaDemo01 {
  def main(args: Array[String]): Unit = {
    val p = new Person("zs",19)
     val person = Person("wagnwu",10)   //不用使用new来创建一个实例
  }
}

class Person(xname :String , xage :Int){
  val name = "zs"
  val age = xage
  var gender = "m"
  def this(name:String,age:Int,g:String){
    this(name,age)
    gender = g
  }
}

object Person{
  def apply(name:String,age:Int)={
    new Person(name,age)  
  }
}

4.if{…}else{…}语句

    /**
     * if else 
     */
    val age =18 
    if (age < 18 ){
    	println("no allow")
    }else if (18<=age&&age<=20){
    	println("allow with other")
    }else{
    	println("allow self")
    }

5.for ,while,do…while
    ①to和until 的用法(不带步长,带步长区别)

 /**
     * to和until
     * 例:
     * 1 to 10 返回1到10的Range数组,包含10
     * 1 until 10 返回1到10 Range数组 ,不包含10
     */
    
    println(1 to 10 )//打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
    
    println(1 to (10 ,2))//步长为2,从1开始打印 ,1,3,5,7,9
    
    println(1 until 10 ) //不包含最后一个数,打印 1,2,3,4,5,6,7,8,9
    
    println(1 until (10 ,3 ))//步长为2,从1开始打印,打印1,4,7

    ②for循环(可加判断条件)

    //可以分号隔开,写入多个list赋值的变量,构成多层for循环
    //scala中 不能写count++ count-- 只能写count+
    //可以在for循环中加入条件判断
    var count = 0;
    for(i <- 1 to 10; j <- 1 until 10;if (i%2) == 0){
      println("i="+ i +",j="+j)
      count += 1
    }
    println(count);
    
    //例子: 打印小九九
    for(i <- 1 until 10 ;j <- 1 until 10){
      if(i>=j){
    	  print(i +" * " + j + " = "+ i*j+"	")  
      }
      if(i==j ){
        println()
      }
    }

补充: for循环用yield 关键字返回一个集合

/*
 *  yield 关键字
 *  1-100集合中的偶数存储到另一个集合
 *  yield关键字能够将符合要求的元素自动封装到一个集合中
 */
val rest = for(i <- 1 to 100; if i%2 == 0) yield i     //此时rest就为选择出的i构成的一个集合
for(elem <- rest) println(elem)

    ③while循环,while(){},do {}while()

   /**
     * while 循环
     */
    var index = 0 
    while(index < 100 ){
    	println("第"+index+"次while 循环")
      index += 1 
    }
    index = 0 
    do{
    	index +=1 
    	println("第"+index+"次do while 循环")
}while(index <100 )

6.函数
    ①普通函数

def fun (a: Int , b: Int ) : Unit = {
   println(a+b)
 }
fun(1,1)
    
def fun1 (a : Int , b : Int)= a+b
    println(fun1(1,2))  

    ②递归函数

 /**
     * 递归函数 
     * 5的阶乘
     */
    def fun2(num :Int) :Int= {  //必须写返回值类型
      if(num ==1)
        num
      else 
        num * fun2(num-1)
    }
    print(fun2(5))

    ③包含参数默认值的函数

 /**
   * 包含参数默认值的函数
   * 	1.	函数的参数有默认值,在调函数的时候可以传参,也可以不传参,
   * 	2.	若不传参使用的默认值,
   * 	3.	如果传参,默认值会被覆盖
   */
  def fun2(num1:Int = 10,num2:Int = 20) = {
    num1 + num2
  }
  
  def fun3(num1:Int,num2:Int = 20) = {
    num1 + num2
  }
  
  def fun4(num1:Int=10,num2:Int) = {
    num1 + num2
  }
  调用:
   println(fun2())
   println(fun3(100))
   println(fun4(num2=1000))

    ④可变参数个数的函数:函数参数可以是一个也可以是多个,随机灵活的

 def fun5(args:Double*) = {
    /**
     * 在scala中
     * 		+=前后的数值类型必须一致
     * 		+前后的数值类型可以不一致
     */
    var sum = 0.0
    for(arg <- args) sum += arg
    sum
  }

    ⑤匿名函数:没有函数名的函数

/**
 * 匿名函数
 * 1.有参数匿名函数
 * 2.无参数匿名函数
 * 3.有返回值的匿名函数
 * 注意:
 * 可以将匿名函数返回给定义的一个变量
 * 匿名函数不能显式声明函数的返回类型

 */
//有参数匿名函数
val value1 = (a : Int) => {
  println(a)
}
value1(1)
//无参数匿名函数
val value2 = ()=>{
  println("我爱Angelababy")
}
value2()
//有返回值的匿名函数
val value3 = (a:Int,b:Int) =>{
  a+b
}
println(value3(4,4)) 

    ⑥嵌套函数

    /**
     * 嵌套函数:
     * 		在函数体内有定义了一个函数
     */
    def fun7(num:Int)={
      def fun8(a:Int,b:Int):Int={
        if(a == 1){
          b
        }else{
          fun8(a-1,a*b)
        }
      }
      fun8(num,1)
    }

    ⑦偏应用函数:偏应用函数是一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。在多个函数调用时,有共同的参数被使用,则可提取出来默认写死,只需要为函数提供部分的参数。

/**
 * 偏应用函数
 */
def log(date :Date, s :String)= {
  println("date is "+ date +",log is "+ s)
}

val date = new Date()
log(date ,"log1")
log(date ,"log2")
log(date ,"log3")

//想要调用log,以上变化的是第二个参数,可以用偏应用函数处理
val logWithDate = log(date,_:String)    //下划线相当于占位符的作用,手动传入即可
logWithDate("log11")
logWithDate("log22")
logWithDate("log33")

    ⑧ 高阶函数:函数的参数是函数,或者函数的返回类型是函数,或者函数的参数和函数的返回类型是函数的函数。

 //函数的参数是函数
    def hightFun(f : (Int,Int) =>Int, a:Int ) : Int = {
      f(a,100)
    }
    def f(v1 :Int,v2: Int):Int  = {
      v1+v2
    }
    
    println(hightFun(f, 1))
    
    //函数的返回是函数
    //1,2,3,4相加
    def hightFun2(a : Int,b:Int) : (Int,Int)=>Int = {
      def f2 (v1: Int,v2:Int) :Int = {
        v1+v2+a+b
      }
      f2
    }
    println(hightFun2(1,2)(3,4))
    
    //函数的参数是函数,函数的返回是函数
    def hightFun3(f : (Int ,Int) => Int) : (Int,Int) => Int = {
      f
    } 
    println(hightFun3(f)(100,200))
    println(hightFun3((a,b) =>{a+b})(200,200))
    //以上这句话还可以写成这样
    //如果函数的参数在方法体中只使用了一次 那么可以写成_表示
    println(hightFun3(_+_)(200,200))

    ⑨柯里化函数

    /**
       * 柯里化函数
       * 		可以理解为高阶函数的简化
       * 		klhFun函数就是对嵌套函数这种情况的高阶函数的简化版
       */

      def klhFun(a:Int)(b:Int) = a*b
      具体:
      def klhAllFun(a:Int):(Int)=>Int = {
        val fun = (b:Int)=>a*b
        fun
      }

7.Scala字符串

val str1 = "hello bi"
    val str2 = "hello sh"
    val flag = str1.equalsIgnoreCase(str2)    
    println(flag)
    
    str1.split(" ")

    val strBuilder = new StringBuilder
    strBuilder.append("hello\t")
    strBuilder.append("bj")
    println(strBuilder)
    println("hello Angelababy".hashCode())

string操作方法举例
1.比较:equals
2.比较忽略大小写:equalsIgnoreCase
3.indexOf:如果字符串中有传入的assci码对应的值,返回下标

  /**
     * String && StringBuilder
     */
    val str = "abcd"
    val str1 = "ABCD"
    
    println(str.indexOf(97))
    println(str.indexOf("b"))

    println(str==str1)
    /**
     * compareToIgnoreCase
     * 
     * 如果参数字符串等于此字符串,则返回值 0;
     * 如果此字符串小于字符串参数,则返回一个小于 0 的值;
     * 如果此字符串大于字符串参数,则返回一个大于 0 的值。
     * 
     */
    println(str.compareToIgnoreCase(str1))
    
    val strBuilder = new StringBuilder
    strBuilder.append("abc")
//    strBuilder.+('d')
    strBuilder+ 'd'
//    strBuilder.++=("efg")
    strBuilder++= "efg" 
//    strBuilder.+=('h')
    strBuilder+= 'h' 
    strBuilder.append(1.0)
    strBuilder.append(18f)
    println(strBuilder)

8.数组

 //数组  new String[10]
    /**
     * Array关键词 创建一个长度为10 的Int类型的数组
     * 如果创建了一个Int类型的数组,那么初始值都是0
     * String类型的数组,初始是null
     * Boolean类型的数组,初始是false
     */
    val nums = new Array[Int](10)
    for(index <- 0 until nums.length){
      nums(index) = index * index
    }
    nums.foreach {println }
    
    //二维数组
    val secArray = new Array[Array[String]](10)
    for(index <- 0 until secArray.length){
      secArray(index) = new Array[String](10)
    }
    
    //往二维数组中填充数据    
   /* for(i <- 0 until secArray.length){
      for(j <- 0 until secArray(i).length){
        secArray(i)(j) = i*j + ""
      }
    }*/
    for(i <- 0 until secArray.length;j <- 0 until secArray(i).length){
      secArray(i)(j) = i*j + ""
    }

9.List集合

   /**
    * list集合
    * 
    * list集合是一个不可变的集合
    * 可变的list集合
    */
    println("=========List==========")
    val list = List(1,2,3,4,5)
    list.contains(6)
    val dropList = list.drop(2)
    dropList.foreach { println }
    list.reverse
    list.take(3).foreach(println)
    val mapList1 = list.map { x=> x +"" }
    mapList1.foreach { x=>println(x) }
    println(list.exists { x => x > 300 })
    println(list.mkString("\t"))
    
    val logList = List("hello bj","hello sh")
    val mapList = logList.map { _.split(" ") }
//    mapList.foreach { x => x.foreach { println } }
    //flatMap方法   flat扁平 
    val flatMapList = logList.flatMap{_.split(" ")}
    flatMapList.foreach { println }

/**
     * 不可变的list集合
     * 创建list集合的方式:
     * 		1、List(1,2,3)
     * 		2、Nil关键创建  Nil:空List
     * 				::往集合中添加元素
     */
    val list = 2::1::Nil
    
    /**
     * 可变的list集合
     */
    val listBuffer = new ListBuffer[String]
    listBuffer.+=("hello")
    listBuffer.+=("bj")
    listBuffer.foreach { println }
    
    listBuffer.-=("hello")

10.set集合

   //创建 
    val set1 = Set(1,2,3,4,4)
    val set2 = Set(1,2,5)
    //遍历
    //注意:set会自动去重
    set1.foreach { println}
   for(s <- set1){
      println(s)
    }
    println("*******")
   /**
    * 方法举例
    */
    
   //交集
   val set3 = set1.intersect(set2)
   set3.foreach{println}
   val set4 = set1.&(set2)
   set4.foreach{println}
   println("*******")
   //差集
   set1.diff(set2).foreach { println }
   set1.&~(set2).foreach { println }
   //子集
   set1.subsetOf(set2)
   
   //最大值
   println(set1.max)
   //最小值
   println(set1.min)
   println("****")
   
   //转成数组,list
   set1.toArray.foreach{println}
   println("****")
   set1.toList.foreach{println}
   
   //mkString
   println(set1.mkString)
   println(set1.mkString("\t"))

11.Map集合

 val map = Map(
                  "1" -> "bj",
                  2 -> "sh",
                  3 -> "gz"
                )
    val keys = map.keys
    val keyIterator = keys.iterator
    while(keyIterator.hasNext){
      val key = keyIterator.next()
      /**
       * map集合的get方法返回值是一个Option类型的对象
       * Option类型有两个子类型  分别为some None
       */
      println(key + "\t" + map.get(key).get)
    }
     
     /**
      * getOrElse 原理:
      * 		去集合中去取数据,若不存在返回默认值
      */
     println(map.get(4).getOrElse("default"))
    
     for(k <- map)
       println(k._1 + "\t" + k._2)
       
     map.foreach(x=>println(x._1 + "\t" + x._2))    
     
     
     map.filter(x=>{
       Integer.parseInt(x._1 + "") >= 2
     }).foreach(println)
     
     val count = map.count(x=>{
       Integer.parseInt(x._1 + "") >= 2
     })
     println(count)

12.元组

 /**
      * 元组 vs list
      * list创建的时候指定了泛型,那么集合中必须是这个泛型的对象
      * 元祖中可以包含任意类型的元素,这些元素使用一对小括号来封装,Tuple关键字
      * 
      * 
      */
     val t2 = Tuple2(1,"hello")
     val tt2 = (1,"hello")
     
     val t3 = Tuple3(1,true,"hello")
     val tt3 = (1,true,"hello")
     
     val moreTuple = (1,2,3)   
     
      val tupleIterator = tt3.productIterator
      while(tupleIterator.hasNext){
      println(tupleIterator.next())
    }
     //toString方法
     println(tt3.toString())
     //swap交换    注意只有二元组对象才会有这个方法
     val swapt2 = tt2.swap
     println(swapt2._1 + "\t" + swapt2._2)

====================================================================================================
附加:

trait 特性

  1. 概念理解 Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。 与接口不同的是,它还可以定义属性和方法的实现。抽象类和接口的结合。
    一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承。Trait(特征) 定义的方式与类类似,但它使用的关键字是
    trait。
  2. 举例:trait中带属性带方法实现 注意:  继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义。  trait中不可以传参数 trait
    Read { val readType = “Read” val gender = “m” def
    read(name:String){ println(name+" is reading") } }

trait Listen { val listenType = “Listen” val gender = “m” def
listen(name:String){ println(name + " is listenning") } }

class Person() extends Read with Listen{ override val gender = “f” }

object test { def main(args: Array[String]): Unit = {
val person = new Person()
person.read(“zhangsan”)
person.listen(“lisi”)
println(person.listenType)
println(person.readType)
println(person.gender)
} }

  1. 举例:trait中带方法不实现
    object Lesson_Trait2 { def main(args: Array[String]): Unit = {
    val p1 = new Point(1,2)
    val p2 = new Point(1,3)
    println(p1.isEqule(p2))
    println(p1.isNotEqule(p2)) } }

trait Equle{ def isEqule(x:Any) :Boolean def isNotEqule(x : Any)
= {
!isEqule(x) } }

class Point(x:Int, y:Int) extends Equle { val xx = x val yy = y

def isEqule(p:Any) = {
p.isInstanceOf[Point] && p.asInstanceOf[Point].xx==xx } } 模式匹配match

  1. 概念理解: Java中的模式匹配为 switch case ; Scala 提供了强大的模式匹配机制,应用也非常广泛,除了匹配值还可以匹配类型,类型的匹配必须要有变量名。
    一个模式匹配包含了一系列备选项,每个都开始于关键字 case。 每个备选项都包含了一个模式及一到多个表达式。箭头符号 =>
    隔开了模式和表达式。
  2. 代码及注意点  模式匹配不仅可以匹配值还可以匹配类型  从上到下顺序匹配,如果匹配到则不再往下匹配  都匹配不上时,会匹配到case _ ,相当于default  match 的最外面的”{ }”可以去掉看成一个语句
     模式匹配的时候,模式范围小的在最前面
    object Lesson_Match { def main(args:
    Array[String]): Unit = {
    val tuple = Tuple6(1,2,3f,4,“abc”,55d)
    val tupleIterator = tuple.productIterator
    while(tupleIterator.hasNext){
    matchTest(tupleIterator.next())
    }
    }
    /** * 注意点: * 1.模式匹配不仅可以匹配值,还可以匹配类型 * 2.模式匹配中,如果匹配到对应的类型或值,就不再继续往下匹配 * 3.模式匹配中,都匹配不上时,会匹配到 case _ ,相当于default */
    def matchTest(x:Any) ={
    x match {
    case x:Int=> println(“type is Int”)
    case 1 => println(“result is 1”)
    case 2 => println(“result is 2”)
    case 3=> println(“result is 3”)
    case 4 => println(“result is 4”)
    case x:String => println(“type is String”) // case x :Double => println(“type is Double”)
    case _ => println(“no match”)
    } } } 样例类(case classes)
  3. 概念理解 使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。
     样例类默认帮你实现了toString,equals,copy和hashCode等方法。  样例类可以new, 也可以不用new
  4. 例子:结合模式匹配的代码 case class Person1(name:String,age:Int)
object Lesson_CaseClass {   def main(args: Array[String]): Unit = {
>     val p1 = new Person1("zhangsan",10)
>     val p2 = Person1("lisi",20)
>     val p3 = Person1("wangwu",30)
>     
>     val list = List(p1,p2,p3)
>     list.foreach { x => {
>       x match {
>         case Person1("zhangsan",10) => println("zhangsan")
>         case Person1("lisi",20) => println("lisi")
>         case _ => println("no match")
>       }
>     } }
>        } }

Actor Model

  1. 概念理解 Actor Model是用来编写并行计算或分布式系统的高层次抽象(类似java中的Thread)让程序员不必为多线程模式下共享锁而烦恼,被用在Erlang
    语言上, 高可用性99.9999999 % 一年只有31ms
    宕机Actors将状态和行为封装在一个轻量的进程/线程中,但是不和其他Actors分享状态,每个Actors有自己的世界观,当需要和其他Actors交互时,通过发送事件和消息,发送是异步的,非堵塞的(fire-andforget),发送消息后不必等另外Actors回复,也不必暂停,每个Actors有自己的消息队列,进来的消息按先来后到排列,这就有很好的并发策略和可伸缩性,可以建立性能很好的事件驱动系统。
    Actor的特征:  ActorModel是消息传递模型,基本特征就是消息传递  消息发送是异步的,非阻塞的
     消息一旦发送成功,不能修改  Actor之间传递时,自己决定决定去检查消息,而不是一直等待,是异步非阻塞的 什么是Akka Akka
    是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和Scala 的 Actor
    模型应用,底层实现就是Actor,Akka是一个开发库和运行环境,可以用于构建高并发、分布式、可容错、事件驱动的基于JVM的应用。使构建高并发的分布式应用更加容易。
    spark1.6版本之前,spark分布式节点之间的消息传递使用的就是Akka,底层也就是actor实现的。1.6之后使用的netty传输。
  2. 例:Actor简单例子发送接收消息 import scala.actors.Actor

class myActor extends Actor{
def act(){
while(true){
receive {
case x:String => println(“save String =”+ x)
case x:Int => println(“save Int”)
case _ => println(“save default”)
}
} } }

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

//创建actor的消息接收和传递
val actor =new myActor()
//启动
actor.start()
//发送消息写法 ,通过!发送消息
actor ! "i love you !"

} }

  1. 例:Actor与Actor之间通信 case class Message(actor:Actor,msg:Any)

class Actor1 extends Actor{ def act(){
while(true){
receive{
case msg :Message => {
println("i sava msg! = "+ msg.msg)

      msg.actor!"i love you too !"
      }
    case msg :String => println(msg)
    case  _ => println("default msg!")
  }
}   } }

class Actor2(actor :Actor) extends Actor{ actor ! Message(this,“i
love you !”) def act(){ while(true){ receive{
case msg :String => {
if(msg.equals(“i love you too !”)){
println(msg)
actor! “could we have a date !”
}
}
case _ => println(“default msg!”) } } } }

object Lesson_Actor2 { def main(args: Array[String]): Unit = {
val actor1 = new Actor1()
actor1.start()
val actor2 = new Actor2(actor1)
actor2.start() } } Scala的隐式转换系统 隐式转换,在编写程序的时候可以尽量少的去编写代码,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,提高代码质量
隐式值:

隐式视图 隐式转换为目标类型:把一种类型自动转换到另一种类型

当某个函数的参数类型不符合要求时(例如需要Int型但传入了String类型),那么在编译的时候,发现作用域内有一个隐式的方法,正好这个方法的参数是String返回值是Int,此时调用这个隐式方法,返回一个Int值,再将Int值传给方法。

隐式类
1.其所带的构造参数有且只能有一个
2.隐式类必须被定义在类,伴生对象和包对象里
3.隐式类不能是case class(case class在定义会自动生成伴生对象与2矛盾)
4.作用域内不能有与之相同名称的标示符

编译器在abc对象调用getLength时发现对象上并没有getLength方法,此时编译器就会在作用域范围内搜索隐式实体,发现有符合的隐式类(类的构造函数类型符合)可以用来转换成带有getLength方法的util类,便将自己传给构造函数,得到这个类的对象,最终调用getLength方法

相关文章: