Scala学习笔记4——高级编程

Scala学习笔记4——高级编程

  • 泛型

    • 泛型类
    • 泛型函数
    class A[T]
    class B[T,S](val b1 : T, val b2 : S)
    def print[A](content : A){
        println(content)
    }
    print[String]("xxx") //res = "xxx"
    
    • 上下界
    object Bounds extends App{
        vsl p = new Pair("A","B")
        println(p.smaller)
        /
        val s1 = new Student("A")
        val s2 = new Student("B")
    	new Pair(s1,s2) //Pair[Student,Student]
        val p1 = new Person("AA")
        println(pair1.replace(p1))
    }
    //上界
    class Pair[T <: Comparable[T]](val first : T, val second : T){
        def smaller = if(first.compareTo(second) < 0) first else second
    }
    //下界(R是T的超类(父类))
    class Pair[T](val first : T, val second : T){
    	def replace[R >: T](first : R) = new Pair(first,second)
    }
    class Person(val name : String)
    class Student(name : String) extends Person(name)
    
  • 视图界定(view bound)

    在Scala中,如果想标记某一个泛型可以隐式的转换为另一个泛型,可以使用:[T <% Comparable[T]]

    T <% V : T到V的隐式转换

    class Pair3[T <% Comparable[T]](val first: T, val second: T) {
      def smaller = if (first.compareTo(second) < 0) first else second
      override def toString = "(" + first + "," + second + ")"
    }
    
    object Main3 extends App {
      val p = new Pair3(4, 2)
      println(p.smaller)
    }
    
  • 上下文界定(context bound)

    • 上下文界定的形式为T:M,其中M是另一个泛型类,它要求必须存在一个类型为M[T]的隐式值。
    • 下面类定义要求必须存在一个类型为Ordering[T]的隐式值,当你使用了一个使用了隐式值的方法时,传入该隐式参数
    class Pair4[T: Ordering](val first: T, val second: T) {
      def smaller(implicit ord: Ordering[T]) = {
        println(ord)
        if (ord.compare(first, second) < 0) first else second
      }
    
      override def toString = "(" + first + "," + second + ")"
    }
    
    object Main4 extends App{
      override def main(args: Array[String]): Unit = {
        val p4 = new Pair4(1, 2)
        println(p4.smaller)
      }
    }
    
  • Manifest上下文界定

    Manifest是Scala 2.8引入的一个特质,用于编译器在运行时也能获取泛型类型的信息。

  //m代表T的信息
  def test[T] (x:T, m:Manifest[T]) { ... }
  //由于上述做法需要用户手动传入m,显得不好。因此采用下述做法,其中隐式参数m是由编译器根据上下文自动传入的。
  def foo[T](x: List[T]) (implicit m: Manifest[T])
  //可以简化为下式
  def foo[T:Manifest] (x: List[T]) 
  • 类型约束

    • T=:=U 意思为T类型是否等于U类型
    • T<:<U 意思为T类型是否为U或U的子类型
  • T<%U 意思是是否存在T到U的隐式转换

  • 型变

    对于类型C[T]持有类型参数T;给定两个类型A和B,如果满足A <: B,则C[A]与 C[B]之间存在三种关系:

    • 协变: C[A] <: C[B], Scala中使用+标识协变
    • 逆变: C[A] :> C[B], Scala中使用-标识逆变
    • 否则,C是不变的,不变则没有标识
    trait C[+A]   // C is covariant
    trait C[-A]   // C is contravariant
    trait C[A]    // C is nonvariant
    //一般地,“不可变的”类型意味着“型变”,而“可变的”意味着“不变”。
    //其中,对于不可变的(Immutable)类型C[T]
    //如果它是一个生产者,其类型参数应该是协变的,即C[+T];
    //如果它是一个消费者,其类型参数应该是逆变的,即C[-T]。
    
  • 隐式转换(implicit)

    • 为现有的类库增加功能
    object Implicit extends App{
        import Context._ //引进隐式转换 或
        import Context.file2RichFile
        new File("xxx").read
    }
    class RichFile(val file : File){
        def read = Source.fromFile(file.getPath).mkString
    }
    object Context{
        implicit def file2RichFile(f : file) = new RichFile(f)
    }
    
  • 隐式转换规则

    • 如果代码能在不使用隐式转换的前提下通过编译,则不会使用隐式转换。
    • 编译器不会同时使用多个隐式转换
    • 不允许存在二义性的隐式转换
  • 隐式参数

    object AAA{
        def print(content : String)(implicit prefix : String){
            println(prefix + ":" + content)
        }
    }
    object Demo extends App{
        import Context._
        AAA.print("Jack")
        //res = "Hello:Jack",自动赋值
    }
    object Context{
        implicit def ccc : String = "Hello"
    }
    
  • 利用隐式参数进行隐式转换

    def smaller[T](a:T,b:T)(implicit order : Ordered[T]) = if (order(a) < b) a else b
    
  • 隐式类

    • 必须定义在一个class/object/trait里面
    • 构造器中只能带一个不是implicit的参数
    • 作用域中不能有与隐式类类名相同的成员变量,函数名,及object名称。
    object Demo extends App{
        import Context._
        println(1.add2)
    }
    object Context{
        //代表可以为int->HH做隐式转换
        implicit class HH(x : Int) = {
            def add2() = x + 2
        }
    }
    //Ordering混入Comparator接口。
    
    object Demo extends App{
        val l1 = new Line(1)
        val l2 = new Line(2)
        val p3 = new Pair2[Line](l1,l2)
        println(p3.smaller)//报错,缺少隐式的ordering,如何解决?
        implicit object Line extends LineOrdering//(放在最上边)
    }
    
    class Pair2[T : Ordering](val first : T,val second : T){
        //implicity[Ordering[T]]可以获得对应的隐式值
        def smaller(implicit ord : ordering[T]) = 
            if (ord.compare(first,second)<0) first else second
    }
    //有了这个trait,Ordering[Line]就可以发生隐式转换
    trait LineOrdering extends Ordering[Line]{
        override def compare(x : Line,y : Line) {
            if (x.len < y.len) -1
            else if(x.len == y.len) 0
            else 1
        }
    }
    class Line(val len : Double){
        override def toString() = ":" + len
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值