Day62_Scala(五)

本文深入探讨Scala编程中的泛型类与方法,包括协变与逆变的概念,以及如何使用隐式转换增强类型功能。此外,还介绍了Scala Actor与Akka Actor系统的基础知识,展示了如何在实际代码中应用这些概念。
摘要由CSDN通过智能技术生成

第五讲 Scala Actor与Akka

课程大纲

课程内容

学习效果

掌握目标

类型参数

泛型类

掌握

泛型方法

掌握

协变与逆变

了解

隐式转换

隐式转换函数

掌握

AKKA

Scala Actor

了解

自行了解

AKKA Actor

了解

       一、类型参数

(一)泛型类

class XxxDao[T] {
	def insert(t: T): Unit = {
	}
}
trait XxxService[T] {
	def save(t: T): Unit
}
class XxxServiceImpl extends XxxService[User] {
	val dao = new XxxDao[User]()
	override def save(t: User): Unit = {
		dao.insert(t)
	}
}
class XxxController {
	val service = new XxxServiceImpl
	def register(t: User): Unit = {
		service.save(t)
	}
}
class User(name:String, age:Int) {
}

(二)泛型方法、泛型限定和视图界定

1、Scala版

//scala版本的方法泛型

object _02GenericOps {

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

        val arr = Array[Integer](3, -1, 0, 5, -5, 7, 6)

        println("排序前的数组:" + arr.mkString("[", ", ", "]"))

        insertSort(arr)

        println("排序后的数组:" + arr.mkString("[", ", ", "]"))

    }

    /*

        scala中的泛型的限定语法格式

            T <: 类型

        java中的泛型限定语法格式

            T extends 类型

     */

    def insertSort[T <: Comparable[T]](array: Array[T]): Unit = {

        for(x <- 1 until array.length) {

            for(y <- 1 to x reverse) {

                if(array(y).compareTo(array(y - 1)) < 0) {

                    swap(array, y, y - 1)

                }

            }

        }

    }

    private def swap[T](arr: Array[T], y: Int, x: Int): Unit = {

        val temp = arr(y)

        arr(y) = arr(x)

        arr(x) = temp

    }

}

我们将java的版本修正为scala的版本,传入Integer类型的数组,完美解决问题,但是如果传递的是一个Int类型的数组,编译就会报错,如5-1-1所示:

 

这个错误说的是Int类型,不具备比较性,观察Int的源码,如图5-1-2所示:

 

确实没有体现出Comparable的特性,所以是不能直接进行比较,但是Int类型的数据,在Scala中确确实实可以进行加减乘除等等运算,比较也是可以的,所以我们想要让上述代码也能执行成功,就需要将泛型定义的修改为:

[T <: Comparable[T]] ==> [T <%: Comparable[T]]

其中T <% Comparable[T]的操作,其实是对T做了类型的内部转换或者功能的增强,把这种操作我们称之为Scala类型参数(泛型)的视图界定,其本质是通过下面要学习的隐式转换函数来实现的。

(三)、协变与逆变

首先需要明确的是,在java中等号左右两侧的泛型必须是要一致的,不可以出现泛型之间继承关系,纵然类型可以出现继承。

class Person{}
class Student extends Person{}
List<Person> list = new ArrayList<Person>(); //ok
不可以
List<Person> list = new ArrayList<Student>();
or
List<Student> list = new ArrayList<Person>();

Scala是一个非常灵活的语言,java办不到的往往scala可以轻而易举的搞定。

当然默认情况下,Scala也只能支持=左右两侧泛型是一致的,但是为了程序更加的灵活和通用,Scala也支持泛型出现继承关系,所谓协变和逆变。

//泛型的协变和逆变
object _03GenericOps {
    def main(args: Array[String]): Unit = {
        val myList1:MyList[Person] = new MyList[Person]()
        val myList2:MyList[Person] = new MyList[Student]()//泛型的协变        
        val myList3:MyList1[Student] = new MyList1[Person]()//泛型的逆变
    }
}
class MyList[+T] {//泛型协变的定义
}
class MyList1[-T] {//泛型逆变的定义
}
class Person {}
class Student extends Person{}

二、隐式转换

(一)、隐式转换

1、说明

Scala提供的能够将一种类型根据需要,自动转化成其他类型的操作方式,进而可以让原有的类型具备其没有的功能,丰富现有api,而不会对原有的代码造成过多的污染。

Scala支持两种形式的隐式转换:

隐式值:用于给方法提供参数

隐式视图:用于类型间转换或使针对某类型的方法能调用成功

2、隐式值

def main(args: Array[String]): Unit = {
    //关键字修饰,会在当前作用域内查找符合方法参数类型的数据进行使用
    //作用域内,相同类型的数据只能存在一个
    implicit val a = "zhangfei"
    implicit val b = 20
    def person(implicit name:String,age:Int)={
        println(s"name=$name,age=$age")
    }
    //调用方法
    person
}

3、隐式视图

这样,变量source就会在自己的作用域范围内自动的搜索是否有这样的隐式转换,如果有,则自动完成类型转换或者加强。

implicit def double2Int(d:Double):Int = d.toInt
val a:Int = 3.5
println("a=" + a)

(二)、利用隐式转换丰富现有类库的功能

object CatAndDog {
  implicit  def dogCatchMouse(dog:Dog) = new Cat()
  def main(args: Array[String]): Unit = {
      val dog = new Dog
      dog.catMouse("大黄狗")
  }
}
class Cat{
  def catMouse(name:String): Unit ={
    println(name+"catch a mouse")
  }
}
class Dog{
  def wangwangwang(name:String) ={
    println(name+"看门汪汪汪")
  }
}

最简单的其实就是,只要在要转换的变量的作用域内能够访问的到,即可进行自动转换,不需要人工干预。

​    在同一个文件中定义的隐式转换,不需要做任何的干预,但是如果要导入其它类中定义的隐式转换,要想在本类中使用,就必须要像导包一样导入。只要在其作用域到导入,即可。同时这个导入的隐式转换因为和导包一样,也不存在对原有类的结构发生入侵。

​    我们在导入的时候,我们倾向于导入到最靠近变量的部分。越靠近变量,其作用域范围越小,影响越小。

import java.io.File
import scala.io.Source
object MyPredef{
  //定义隐式转换方法
  implicit def file2RichFile(file: File)=new RichFile(file)
}
class RichFile(val f:File) {
  def read()=Source.fromFile(f,"GBK").mkString
}
object RichFile{
  def main(args: Array[String]) {
    val f=new File("F:\\scala与spark课件资料教案\\3、scala第三天\\files\\file.txt")
    //使用import导入隐式转换方法
    import MyPredef._
    //通过隐式转换,让File类具备了RichFile类中的方法
    val content=f.read()
    println(content)
  }
}

说明:隐式转换参数,可以显示的指定,也可以隐式的指定,如果是隐式指定,就需要让该变量在其作用域内访问到被implicit关键字修饰的相关变量,自动进行赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值