scala一些概念简述

记录一些scala中的重要概念

T <: 上界 类型变量界定
T >: 下界 类型变量界定
T <& 存在隐式函数、隐式值 对类型进行视图界定
T >& 存在隐式函数、隐式值 对类型进行视图界定
T : Ordering 上下文界定 T属于ordering类型
classtag 泛型运用反射,编译时虚拟机并不能识别泛型类型,予以擦出,程序运行时,动态获取类型
并把类型赋予给classtag,用以得到具体类型。

协变,B是A的子类,如果list[B]是list[A]的子类则是协变,反之是逆变。

访问权限,默认是public类型,如果是private类型,伴生对象和伴生类之间可以相互访问,
否则不能访问.可以在object中apply方法里new一个类的对象实现,直接调用object就可以
new出对象。如果是private[this]类型,则只能当前对象进行调用[this对象],其他类中
new一个private[this]类型的对象调用该变量也不能调用该变量。

内部类在java和scala中的区别:在java中,内部类需要先new出外部类,然后用.new内部类,内部类的
类型是一样的,直白的说就是同一个对象地址,而scala中的内部类,通过new 外部类.内部类的方式,
对象不是同一个对象,地址不同。

偏函数:直白的说就是用参数调用一个方法,然后再往方法里传参数,返回值。

闭包:定义了一个变量,这个变量,离开了它的作用域,依然可以使用它。

最后说说比较重要的,隐式转换:直白的说,就是本来一个类没有这个方法,但是通过隐式转换,它拥有了这个方法。

隐式转换的时机:

1.当方法中的参数的类型与目标类型不一致时。

2.当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换。

隐式解析机制

即编译器是如何查找到缺失信息的,解析具有以下两种规则:

1.首先会在当前代码作用域下查找隐式实体(隐式方法 隐式类 隐式对象)。

2.如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。

类型的作用域是指与该类型相关联的全部伴生模块,一个隐式实体的类型T它的查找范围如下:

(1)如果T被定义为T with A with B with C,那么A,B,C都是T的部分,在T的隐式解析过程中,它们的伴生对象都会被搜索。

(2)如果T是参数化类型,那么类型参数和与类型参数相关联的部分都算作T的部分,比如List[String]的隐式搜索会搜索List的伴生对象和String的伴生对象。

(3)如果T是一个单例类型p.T,即T是属于某个p对象内,那么这个p对象也会被搜索。

(4)如果T是个类型注入S#T,那么S和T都会被搜索。

隐式转换的前提:

1.不存在二义性。

2.隐式操作不能嵌套使用。

隐式参数使用的常见问题:

  (1)当函数没有柯里化时,implicit关键字会作用于函数列表中的的所有参数。

  (2)隐式参数使用时要么全部不指定,要么全不指定,不能只指定部分。

  (3)同类型的隐式值只能在作用域内出现一次,即不能在同一个作用域中定义多个相同类型的隐式值。

  (4)在指定隐式参数时,implicit 关键字只能出现在参数开头。

  (5)如果想要实现参数的部分隐式参数,只能使用函数的柯里化,

  如要实现这种形式的函数,def test(x:Int, implicit  y: Double)的形式,必须使用柯里化实现:def test(x: Int)(implicit y: Double)。

   (6) 柯里化的函数, implicit 关键字只能作用于最后一个参数。否则,不合法。

   (7)implicit 关键字在隐式参数中只能出现一次,柯里化的函数也不例外。

   (8)匿名函数不能使用隐式参数。

   (9)柯里化的函数如果有隐式参数,则不能使用其偏应用函数。

   (10)单一调用规则:隐式转换只会匹配一次,即隐式转换至多发生一次不会叠加(重复嵌套)使用隐式转换。一次隐式转化调用成功之后,编译器不会再去寻找其他的隐式转换。

   (11)显示操作优先规则:当前代码类型检查没有问题,编译器不会尝试查找隐式转换。

   (12)所有隐式转换必须用implicit关键字修饰。

隐式转换


import scala.io.Source
import java.io.File

//这里的RichFile相当于File的增强类 需要将被增强的类作为参数传入构造器中
class RichFile(val file: File) {
  def read = {
      Source.fromFile(file.getPath).mkString
  }
}
 
//implicit是隐式转换的关键字 这里定义一个隐式转换函数把当前类型转换成增强的类型
object Test {
    //File --> RichFile
    implicit def file2RichFile(file: File) = new RichFile(file)
}
 
object App {
    def main(args: Array[String]): Unit = {
        //导入隐式转换
        import Test.file2RichFile
        //File类本身没有read方法 通过隐式转换完成
        //这里的read方法是RichFile类中的方法  需要通过隐式转换File --> RichFile
        println(new File("D:\\").read)
      
    }
}

隐式值的应用


object Implicits {
    implicit val default: String = "Spark"
}

object Param {
    //函数中用implicit关键字 定义隐式参数
    def print(context: String)(implicit skill: String){
        println(skill+":"+context)
    }
}

object Implicit_Parameters {
    def main(args: Array[String]): Unit = {
        //隐式参数正常是可以传值的,和普通函数传值一样,但是也可以不传值,因为有缺省值(默认配置)
        Param.print("Spark")("MLlib")
        
        import Implicits._
        //隐式参数没有传值,编译器会在全局范围内搜索 有没有implicit String类型的隐式值,并传入
        Param.print("Hadoop")      
    }
}


通过伴生对象隐式转换

import java.io.File
import scala.io.Source
 

class RichFile(val file: File) {
    def read = Source.fromFile(file.getPath).mkString
}

class Test(path: String) extends File(path)
object Test {
    implicit def file2RichFile(file: File) = new RichFile(file) //file-->RichFile
}
 
object Implicits_Internals {
    def main(args: Array[String]): Unit = {
       /*
        * 这里没有导入隐式对象
        * 
        * 通过给Test类 构建一个伴生对象 在伴生对象内部顶一个隐式转换的方法
        * 
        * 执行顺序:
        * 1.搜索Test有无read方法 
        * 2.在上下文上搜索(有无导入的隐式对象)
        * 3.搜索Test的伴生对象内有无隐式转换  发现implicit关键 尝试匹配类型  
        *    例如这里匹配file2RichFile(file: File) 返回类型为RichFile 在RichFile中发现read方法
        */
       println(new Test("D:\\").read)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值