美文网首页
Scala语言学习五 (高级用法)

Scala语言学习五 (高级用法)

作者: 做个合格的大厂程序员 | 来源:发表于2020-08-17 16:53 被阅读0次

    Scala 高级用法

    样例类

    ​ 样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类),在后续要学习并发编程和spark、flink这些框架也都会经常使用它。

    语法

    ase class 样例类名([var/val] 成员变量名1:类型1, 成员变量名2:类型2, 成员变量名3:类型3)    
    

    示例:

    需求

    • 定义一个Person样例类,包含姓名和年龄成员变量
    • 创建样例类的对象实例("张三"、20),并打印它
    object _01CaseClassDemo {
      case class Person(name:String, age:Int)
    
      def main(args: Array[String]): Unit = {
        val zhangsan = Person("张三", 20)
    
        println(zhangsan)
      }
    }
    

    需求

    • 定义一个Person样例类,包含姓名和年龄成员变量
    • 创建样例类的对象实例("张三"、20)
    • 修改张三的年龄为23岁,并打印
    object _02CaseClassDemo {
      case class Person(var name:String, var age:Int)
    
      def main(args: Array[String]): Unit = {
        val zhangsan = Person("张三", 20)
    
        zhangsan.age = 23
    
        println(zhangsan)
      }
    }
    

    样例类的方法

    当我们定义一个样例类,编译器自动帮助我们实现了以下几个有用的方法:

    • apply方法
    • toString方法
    • equals方法
    • hashCode方法
    • copy方法

    apply方法

    apply方法可以让我们快速地使用类名来创建对象。参考以下代码:

    case class CasePerson(name:String, age:Int)
    
    object CaseClassDemo {
      def main(args: Array[String]): Unit = {
        val lisi = CasePerson("李四", 21)
        println(lisi.toString)
      }
    }
    

    默认就是用apply方法

    toString方法

    toString返回样例类名称(成员变量1, 成员变量2, 成员变量3....),我们可以更方面查看样例类的成员

    case class CasePerson(name:String, age:Int)
    
    object CaseClassDemo {
      def main(args: Array[String]): Unit = {
        val lisi = CasePerson("李四", 21)
        println(lisi.toString)
        // 输出:CasePerson(李四,21)
      }
    }
    

    默认也可以不用写toString,直接打印类名直接就是toString的功能

    equals方法

    样例类自动实现了equals方法,可以直接使用==比较两个样例类是否相等,即所有的成员变量是否相等

    示例

    • 创建一个样例类Person,包含姓名、年龄
    • 创建名字年龄分别为"李四", 21的两个对象
    • 比较它们是否相等
    val lisi1 = CasePerson("李四", 21)
    val lisi2 = CasePerson("李四", 21)
    println(lisi1 == lisi2)
    // 输出:true
    

    hashCode方法

    样例类自动实现了hashCode方法,如果所有成员变量的值相同,则hash值相同,只要有一个不一样,则hash值不一样。

    示例

    • 创建名字年龄分别为"李四", 21的对象
    • 再创建一个名字年龄分别为"李四", 22的对象
    • 分别打印这两个对象的哈希值
    val lisi1 = CasePerson("李四", 21)
    val lisi2 = CasePerson("李四", 22)
    
    println(lisi1.hashCode())
    println(lisi2.hashCode())
    

    copy方法

    样例类实现了copy方法,可以快速创建一个相同的实例对象,可以使用带名参数指定给成员进行重新赋值

    示例

    • 创建名字年龄分别为"李四", 21的对象
    • 通过copy拷贝,名字为"王五"的对象
    **示例**
    
    - 创建名字年龄分别为"李四", 21的对象
    - 通过copy拷贝,名字为"王五"的对象
    

    样例对象

    语法

    case object 样例对象名
    

    示例

    需求说明

    • 定义一个性别Sex枚举,它只有两个实例(男性——Male、女性——Female)
    • 创建一个Person类,它有两个成员(姓名、性别)
    • 创建两个Person对象("张三"、男性)、("李四"、"女")
    trait Sex /*定义一个性别特质*/
    case object Male extends Sex        // 定义一个样例对象并实现了Sex特质
    case object Female extends Sex      
    
    case class Person(name:String, sex:Sex)
    
    object CaseClassDemo {
      def main(args: Array[String]): Unit = {
        val zhangsan = Person("张三", Male)
    
        println(zhangsan)
      }
    }
    

    模式匹配

    简单匹配模式

    在Java中,有switch关键字,可以简化if条件判断语句。在scala中,可以使用match表达式替代。

    语法

    变量 match {
        case "常量1" => 表达式1
        case "常量2" => 表达式2
        case "常量3" => 表达式3
        case _ => 表达式4      // 默认匹配
    }
    

    示例

    需求说明

    1. 从控制台输入一个单词(使用StdIn.readLine方法)
    2. 判断该单词是否能够匹配以下单词,如果能匹配,返回一句话
    3. 打印这句话
    println("请输出一个词:")
    // StdIn.readLine表示从控制台读取一行文本
    val name = StdIn.readLine()
    
    val result = name match {
        case "hadoop" => "大数据分布式存储和计算框架"
        case "zookeeper" => "大数据分布式协调服务框架"
        case "spark" => "大数据分布式内存计算框架"
        case _ => "未匹配"
    }
    
    println(result)
    

    匹配类型

    语法

    变量 match {
        case 类型1变量名: 类型1 => 表达式1
        case 类型2变量名: 类型2 => 表达式2
        case 类型3变量名: 类型3 => 表达式3
        ...
        case _ => 表达式4
    }
    

    示例

    需求说明

    • 定义一个变量为Any类型,然后分别给其赋值为"hadoop"、1、1.0
    • 定义模式匹配,然后分别打印类型的名称
    val a:Any = "hadoop"
    
    val result = a match {
        case _:String => "String"
        case _:Int => "Int"
        case _:Double => "Double"
    }
    
    println(result)
    

    守卫

    就是java中case方法里的default,也就是说在没有匹配到值得情况下得取一个默认的值

    示例

    需求说明

    • 从控制台读入一个数字a(使用StdIn.readInt)
    • 如果 a >= 0 而且 a <= 3,打印[0-3]
    • 如果 a >= 4 而且 a <= 8,打印[3,8]
    • 否则,打印未匹配
    val a = StdIn.readInt()
    
    a match {
        case _ if a >= 0 && a <= 3 => println("[0-3]")
        case _ if a >= 4 && a <= 8 => println("[3-8]")
        case _ => println("未匹配")
    }
    

    匹配样例类

    scala可以使用模式匹配来匹配样例类,从而可以快速获取样例类中的成员数据。后续,我们在开发Akka案例时,还会用到。

    需求说明

    • 创建两个样例类Customer、Order
      • Customer包含姓名、年龄字段
      • Order包含id字段
    • 分别定义两个案例类的对象,并指定为Any类型
    • 使用模式匹配这两个对象,并分别打印它们的成员变量值
    / 1. 创建两个样例类
    case class Person(name:String, age:Int)
    case class Order(id:String)
    
    def main(args: Array[String]): Unit = {
        // 2. 创建样例类对象,并赋值为Any类型
        val zhangsan:Any = Person("张三", 20)
        val order1:Any = Order("001")
    
        // 3. 使用match...case表达式来进行模式匹配
        // 获取样例类中成员变量
        order1 match {
            case Person(name, age) => println(s"姓名:${name} 年龄:${age}")
            case Order(id1) => println(s"ID为:${id1}")
            case _ => println("未匹配")
        }
    }
    

    匹配集合,列表,元祖

    匹配集合

    scala中的模式匹配,还能用来匹配集合。

    示例

    • 依次修改代码定义以下三个数组

      Array(1,x,y)   // 以1开头,后续的两个元素不固定
      Array(0)     // 只匹配一个0元素的元素
      Array(0, ...)  // 可以任意数量,但是以0开头
      
    • 使用模式匹配上述数组

    val arr = Array(1, 3, 5)
    arr match {
        case Array(1, x, y) => println(x + " " + y)
        case Array(0) => println("only 0")
        case Array(0, _*) => println("0 ...")
        case _ => println("something else")
    }
    

    匹配列表

    示例

    • 依次修改代码定义以下三个列表

      List(0)               // 只保存0一个元素的列表
      List(0,...)           // 以0开头的列表,数量不固定
      List(x,y)         // 只包含两个元素的列表  
      
    • 使用模式匹配上述列表

    val list = List(0, 1, 2)
    
    list match {
        case 0 :: Nil => println("只有0的列表")
        case 0 :: tail => println("0开头的列表")
        case x :: y :: Nil => println(s"只有另两个元素${x}, ${y}的列表")
        case _ => println("未匹配")
    }
    

    匹配元祖

    • 依次修改代码定义以下两个元组

      (1, x, y)     // 以1开头的、一共三个元素的元组
      (x, y, 5)   // 一共有三个元素,最后一个元素为5的元组
      
    • 使用模式匹配上述元素

    val tuple = (2, 2, 5)
    
    tuple match {
        case (1, x, y) => println(s"三个元素,1开头的元组:1, ${x}, ${y}")
        case (x, y, 5) => println(s"三个元素,5结尾的元组:${x}, ${y}, 5")
        case _ => println("未匹配")
    }
    

    Option 类型

    使用Option类型,可以用来有效避免空引用(null)异常。也就是说,将来我们返回某些数据时,可以返回一个Option类型来替代。

    • Some(x):表示实际的值

    • None:表示没有值

    • 使用getOrElse方法,当值为None是可以指定一个默认值

    示例说明

    • 定义一个两个数相除的方法,使用Option类型来封装结果
    • 然后使用模式匹配来打印结果
      • 不是除零,打印结果
      • 除零打印异常错误
      /**
        * 定义除法操作
        * @param a 参数1
        * @param b 参数2
        * @return Option包装Double类型
        */
      def dvi(a:Double, b:Double):Option[Double] = {
        if(b != 0) {
          Some(a / b)
        }
        else {
          None
        }
      }
    
      def main(args: Array[String]): Unit = {
        val result1 = dvi(1.0, 5)
    
        result1 match {
          case Some(x) => println(x)
          case None => println("除零异常")
        }
      } 
    

    示例说明

    • 重写上述案例,使用getOrElse方法,当除零时,或者默认值为0
    def dvi(a:Double, b:Double) = {
        if(b != 0) {
            Some(a / b)
        }
        else {
            None
        }
    }
    
    def main(args: Array[String]): Unit = {
        val result = dvi(1, 0).getOrElse(0)
    
        println(result)
    }
    

    偏函数

    偏函数可以提供了简洁的语法,可以简化函数的定义。配合集合的函数式编程,可以让代码更加优雅。

    定义

    • 偏函数被包在花括号内没有match的一组case语句是一个偏函数

    • 偏函数是PartialFunction[A, B]的一个实例

      • A代表输入参数类型
      • B代表返回结果类型

    示例说明*

    定义一个偏函数,根据以下方式返回

    1->一

    2->二

    3->三

    其他 —> 其他

    // func1是一个输入参数为Int类型,返回值为String类型的偏函数
    val func1: PartialFunction[Int, String] = {
        case 1 => "一"
        case 2 => "二"
        case 3 => "三"
        case _ => "其他"
    }
    
    println(func1(2))
    

    示例说明

    • 定义一个列表,包含1-10的数字
    • 请将1-3的数字都转换为[1-3]
    • 请将4-8的数字都转换为[4-8]
    • 将其他的数字转换为(8-*]
    val list = (1 to 10).toList
    
    val list2 = list.map{
        case x if x >= 1 && x <= 3 => "[1-3]"
        case x if x >= 4 && x <= 8 => "[4-8]"
        case x if x > 8 => "(8-*]"
    }
    
    println(list2)
    

    正则表达式

    Regex类

    • scala中提供了Regex类来定义正则表达式

    • 要构造一个RegEx对象,直接使用String类的r方法即可

    • 建议使用三个双引号来表示正则表达式,不然就得对正则中的反斜杠来进行转义

    val regEx = """正则表达式""".r
    

    findAllMatchIn方法

    使用findAllMatchIn方法可以获取到所有正则匹配到的字符串

    示例说明

    • 定义一个正则表达式,来匹配邮箱是否合法
    • 合法邮箱测试:qq12344@163.com
    • 不合法邮箱测试:qq12344@.com
    val r = """.+@.+\..+""".r
    
    val eml1 = "qq12344@163.com"
    val eml2 = "qq12344@.com"
    
    if(r.findAllMatchIn(eml1).size > 0) {
        println(eml1 + "邮箱合法")
    }
    else {
        println(eml1 + "邮箱不合法")
    }
    
    if(r.findAllMatchIn(eml2).size > 0) {
        println(eml2 + "邮箱合法")
    }
    else {
        println(eml2 + "邮箱不合法")
    }
    

    示例说明

    找出以下列表中的所有不合法的邮箱

    "38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com"
    
    val emlList =
    List("38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com")
    
    val regex = """.+@.+\..+""".r
    
    val invalidEmlList = emlList.filter {
        x =>
        if (regex.findAllMatchIn(x).size < 1) true else false
    }
    
    println(invalidEmlList)
    

    异常处理

    下面一段代码

    def main(args: Array[String]): Unit = {
       val i = 10 / 0
        
        println("你好!")
      }
    
    Exception in thread "main" java.lang.ArithmeticException: / by zero
        at ForDemo$.main(ForDemo.scala:3)
        at ForDemo.main(ForDemo.scala)
    

    执行程序,可以看到scala抛出了异常,而且没有打印出来"你好"。说明程序出现错误后就终止了。

    那怎么解决该问题呢?

    在scala中,可以使用异常处理来解决这个问题

    语法

    try {
        // 代码
    }
    catch {
        case ex:异常类型1 => // 代码
        case ex:异常类型2 => // 代码
    }
    finally {
        // 代码
    }
    
    • try中的代码是我们编写的业务处理代码
    • 在catch中表示当出现某个异常时,需要执行的代码
    • 在finally中,是不管是否出现异常都会执行的代码

    示例说明

    • 使用try..catch来捕获除零异常
    try {
        val i = 10 / 0
    
        println("你好!")
    } catch {
        case ex: Exception => println(ex.getMessage)
    } 
    

    抛出异常

    我们也可以在一个方法中,抛出异常。语法格式和Java类似,使用throw new Exception...

    示例说明

    • 在main方法中抛出一个异常
      def main(args: Array[String]): Unit = {
        throw new Exception("这是一个异常")
      }
    
    Exception in thread "main" java.lang.Exception: 这是一个异常
        at ForDemo$.main(ForDemo.scala:3)
        at ForDemo.main(ForDemo.scala)
    

    提取器

    之前我们学习过了,实现一个类的伴生对象中的apply方法,可以用类名来快速构建一个对象。伴生对象中,还有一个unapply方法。与apply相反,unapply是将该类的对象,拆解为一个个的元素。

    1552639637165 1552639674932

    语法

    def unapply(stu:Student):Option[(类型1, 类型2, 类型3...)] = {
        if(stu != null) {
            Some((变量1, 变量2, 变量3...))
        }
        else {
            None
        }
    }
    

    示例说明

    • 创建一个Student类,包含姓名年龄两个字段
    • 实现一个类的解构器,并使用match表达式进行模式匹配,提取类中的字段。
    class Student(var name:String, var age:Int)
    
    object Student {
        def apply(name:String, age:Int) = {
            new Student(name, age)
        }
    
        def unapply(student:Student) = {
            val tuple = (student.name, student.age)
    
            Some(tuple)
        }
    }
    
    def main(args: Array[String]): Unit = {
        val zhangsan = Student("张三", 20)
    
        zhangsan match {
            case Student(name, age) => println(s"${name} => ${age}")
        }
    }
    

    泛型

    scala和Java一样,类和特质、方法都可以支持泛型。我们在学习集合的时候,一般都会涉及到泛型。

    scala> val list1:List[String] = List("1", "2", "3")
    list1: List[String] = List(1, 2, 3)
    

    语法

    def 方法名[泛型名称](..) = {
        //...
    }
    

    不考虑泛型

    ef getMiddle(arr:Array[Int]) = arr(arr.length / 2)
    
      def main(args: Array[String]): Unit = {
        val arr1 = Array(1,2,3,4,5)
    
        println(getMiddle(arr1))
      }
    

    加入泛型之后

    def getMiddleElement[T](array:Array[T]) =
    array(array.length / 2)
    
    def main(args: Array[String]): Unit = {
        println(getMiddleElement(Array(1, 2, 3, 4, 5)))
        println(getMiddleElement(Array("a", "b", "c", "d", "e")))
    }
    

    泛型类

    scala的类也可以定义泛型。接下来,我们来学习如何定义scala的泛型类

    语法

    class 类[T](val 变量名: T)
    

    示例说明

    • 实现一个Pair泛型类
    • Pair类包含两个字段,而且两个字段的类型不固定
    • 创建不同类型泛型类对象,并打印
    case class Pair[T](var a:T, var b:T)
    
    def main(args: Array[String]): Unit = {
        val pairList = List(
            Pair("Hadoop", "Storm"),
            Pair("Hadoop", 2008),
            Pair(1.0, 2.0),
            Pair("Hadoop", Some(1.9))
        )
    
        println(pairList)
    }
    

    泛型的上下界

    我们在定义方法/类的泛型时,限定必须从哪个类继承、或者必须是哪个类的父类。此时,就需要使用到上下界。

    上界定义

    使用<: 类型名表示给类型添加一个上界,表示泛型参数必须要从该类(或本身)继承

    [T <: 类型]
    

    示例说明

    • 定义一个Person类
    • 定义一个Student类,继承Person类
    • 定义一个demo泛型方法,该方法接收一个Array参数,
    • 限定demo方法的Array元素类型只能是Person或者Person的子类
    • 测试调用demo,传入不同元素类型的Array
    class Person
    class Student extends Person
    
    def demo[T <: Person](a:Array[T]) = println(a)
    
    def main(args: Array[String]): Unit = {
        demo(Array(new Person))
        demo(Array(new Student))
        // 编译出错,必须是Person的子类
        // demo(Array("hadoop"))
    }
    

    下界定义

    上界是要求必须是某个类的子类,或者必须从某个类继承,而下界是必须是某个类的父类(或本身)

    [T >: 类型]
    

    示例说明

    • 定义一个Person类
    • 定义一个Policeman类,继承Person类
    • 定义一个Superman类,继承Policeman类
    • 定义一个demo泛型方法,该方法接收一个Array参数,
    • 限定demo方法的Array元素类型只能是Person、Policeman
    • 测试调用demo,传入不同元素类型的Array
    class Person
    class Policeman extends Person
    class Superman extends Policeman
    
    def demo[T >: Policeman](array:Array[T]) = println(array)
    
    def main(args: Array[String]): Unit = {
        demo(Array(new Person))
        demo(Array(new Policeman))
        // 编译出错:Superman是Policeman的子类
        // demo(Array(new Superman))
    }
    

    协变、逆变、非变 (掌握)

    spark的源代码中大量使用到了协变、逆变、非变,学习该知识点对我们将来阅读spark源代码很有帮助。

    class Pair[T]
    
    object Pair {
      def main(args: Array[String]): Unit = {
        val p1 = Pair("hello")
        // 编译报错,无法将p1转换为p2
        val p2:Pair[AnyRef] = p1
    
        println(p2)
      }
    }
    
    1558064807949

    非变

    class Pair[T]{}
    
    • 默认泛型类是非变的
    • 类型B是A的子类型,Pair[A]和Pair[B]没有任何从属关系
    • Java是一样的

    协变

    class Pair[+T]
    
    • 类型B是A的子类型,Pair[B]可以认为是Pair[A]的子类型
    • 参数化类型的方向和类型的方向是一致的。

    逆变

    class Pair[-T]
    
    • 类型B是A的子类型,Pair[A]反过来可以认为是Pair[B]的子类型
    • 参数化类型的方向和类型的方向是相反的

    示例

    • 定义一个Super类、以及一个Sub类继承自Super类
    • 使用协变、逆变、非变分别定义三个泛型类
    • 分别创建泛型类来演示协变、逆变、非变
    class Super
    class Sub extends Super
    
    class Temp1[T]
    class Temp2[+T]
    class Temp3[-T]
    
    def main(args: Array[String]): Unit = {
        val a:Temp1[Sub] = new Temp1[Sub]
        // 编译报错
        // 非变
        //val b:Temp1[Super] = a
    
        // 协变
        val c: Temp2[Sub] = new Temp2[Sub]
        val d: Temp2[Super] = c
    
        // 逆变
        val e: Temp3[Super] = new Temp3[Super]
        val f: Temp3[Sub] = e
    }
    

    Actor 介绍

    Actor并发编程模型,是scala提供给程序员的一种与Java并发编程完全不一样的并发编程模型,是一种基于事件模型的并发机制。Actor并发编程模型是一种不共享数据,依赖消息传递的一种并发编程模式,有效避免资源争夺、死锁等情况。

    1552787528554

    创建Actor

    创建Actor的方式和Java中创建线程很类似,也是通过继承来创建。

    1. 定义class或object继承Actor特质
    2. 重写act方法
    3. 调用Actor的start方法执行Actor

    示例说明

    创建两个Actor,一个Actor打印1-10,另一个Actor打印11-20

    • 使用class继承Actor创建(如果需要在程序中创建多个相同的Actor)
    • 使用object继承Actor创建(如果在程序中只创建一个Actor)
    object _05ActorDemo {
      class Actor1 extends Actor {
        override def act(): Unit = (1 to 10).foreach(println(_))
      }
    
      class Actor2 extends Actor {
        override def act(): Unit = (11 to 20).foreach(println(_))
      }
    
      def main(args: Array[String]): Unit = {
        new Actor1().start()
        new Actor2().start()
      }
    }
    

    使用object继承Actor创建

      object Actor1 extends Actor {
        override def act(): Unit =
          for(i <- 1 to 10) {
            println(i)
          }
      }
    
      object Actor2 extends Actor {
        override def act(): Unit =
          for(i <- 11 to 20) {
            println(i)
          }
      }
    
      def main(args: Array[String]): Unit = {
        Actor1.start()
        Actor2.start()
      }
    

    Actor程序运行流程

    1. 调用start()方法启动Actor
    2. 自动执行act()方法
    3. 向Actor发送消息
    4. act方法执行完成后,程序会调用exit()方法

    Actor 发送接收消息

    我们之前介绍Actor的时候,说过Actor是基于事件(消息)的并发编程模型,那么Actor是如何发送消息和接收消息的呢?

    发送异步消息,没有返回值
    !? 发送同步消息,等待返回值
    !! 发送异步消息,返回值是Future[Any]

    要给actor1发送一个异步字符串消息,使用以下代码:

    ctor1 ! "你好!"
    

    接收消息

    Actor中使用receive方法来接收消息,需要给receive方法传入一个偏函数

    {
        case 变量名1:消息类型1 => 业务处理1,
        case 变量名2:消息类型2 => 业务处理2,
        ...
    }
    

    示例说明

    • 创建两个Actor(ActorSender、ActorReceiver)
    • ActorSender发送一个异步字符串消息给ActorReceiver
    • ActorReceive接收到该消息后,打印出来
    1552791021244
      object ActorSender extends Actor {
        override def act(): Unit = {
          // 发送消息
          while(true) {
            ActorReceiver ! "hello!"
            TimeUnit.SECONDS.sleep(3)
          }
        }
      }
    
      object ActorReceiver extends Actor {
        override def act(): Unit = {
          // 持续接收消息
          while(true) {
            receive {
              case msg:String => println("接收到消息:" + msg)
            }
          }
        }
      }
    
      def main(args: Array[String]): Unit = {
        ActorReceiver.start()
        ActorSender.start()
      }
    

    Actor 的Loop

    上述代码,使用while循环来不断接收消息。

    • 如果当前Actor没有接收到消息,线程就会处于阻塞状态
    • 如果有很多的Actor,就有可能会导致很多线程都是处于阻塞状态
    • 每次有新的消息来时,重新创建线程来处理
    • 频繁的线程创建、销毁和切换,会影响运行效率

    在scala中,可以使用loop + react来复用线程。比while + receive更高效

    用Loop改写上述代码

    // 持续接收消息
    loop {
        react {
            case msg:String => println("接收到消息:" + msg)
        }
    }
    

    Actor 举例说明

    示例一

    示例说明

    • 创建一个MsgActor,并向它发送一个同步消息,该消息包含两个字段(id、message)
    • MsgActor回复一个消息,该消息包含两个字段(message、name)
    • 打印回复消息
      case class Message(id:Int, msg:String)
      case class ReplyMessage(msg:String, name:String)
    
      object MsgActor extends Actor {
        override def act(): Unit = {
          loop {
            react {
              case Message(id, msg) => {
                println(s"接收到消息:${id}/${msg}")
                sender ! ReplyMessage("不太好", "Tom")
              }
            }
          }
        }
      }
    
      def main(args: Array[String]): Unit = {
        MsgActor.start()
    
        val replyMessage: Any = MsgActor !? Message(1, "你好")
        println("回复消息:" + replyMessage.asInstanceOf[ReplyMessage])
      }
    

    相关文章

      网友评论

          本文标题:Scala语言学习五 (高级用法)

          本文链接:https://www.haomeiwen.com/subject/urvqjktx.html