当前位置: 首页 > 工具软件 > Scala.Rx > 使用案例 >

5.Scala基础—样例类、隐式转换、Actor Model

金健
2023-12-01

第八章 样例类(Case Classes)

8.1 概念

使用了case关键字的类定义就是样例类case classes,样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现settergetter方法。

  • 样例类默认帮你实现了toString , equals, copyhashCode等方法。
  • 样例类可以new ,也可以不用new

8.2 具体写法

结合模式匹配的代码如下:

case class Person(name :String, age : Int)

object Lesson_Caseclass {
	def main(args: Array [String]) : Unit = {
		val p1 = new Person("zhangsan", 10)
		val p2 = Person("lisi", 20)
		val p3 = Person("wangwu", 30)
		
		val list = List(p1, p2, p3)
		list.foreach{ x => {
			x match {
				case Person("zhangsan", 10) => println("zhangsan")
				case x:Person => println("person")
				case Person("lisi", 20) => println("lisi")
				case _ => println("no match")
			}}
		}
	}
}

第九章 隐式转换(重要)

9.1 概念

隐式转换是在Scala编译器进行类型匹配时,如果找不到合适的类型,那么隐式转换会让编译器在作用范围内自动推导出来合适的类型。

9.2 隐式值与隐式参数

隐式值是指在定义参数时前面加上implicit。隐式参数是指在定义方法时,方法中的部分参数是由implicit修饰【必须使用柯里化的方式,将隐式参数写在后面的括号中】。隐式转换作用就是:当调用方法时,不必手动传入方法中的隐式参数,Scala会自动在作用域范围内寻找隐式值自动传入。

9.2.1 注意点

  • (1) 同类型的参数的隐式值只能在作用域内出现一次,同一个作用域内不能定义多个类型一样的隐式值。
  • (2) implicit关键字必须放在隐式参数定义的开头
  • (3) 一个方法只有一个参数是隐式转换参数时,那么可以直接定义implicit关键字修饰的参数,调用时直接创建类型不传入参数即可。
  • (4) 一个方法如果有多个参数,要实现部分参数的隐式转换,必须使用柯里化这种方式,隐式关键字出现在后面,只能出现一次。

9.2.2 具体方法

object Test_Implicit {
	//隐式值
	implicit val address : String = "shanghai"
	implicit val num: Int= 20
	// 注:相同类型的隐式值只能有一个

	//隐式参数
	def test(implicit name: Int): Unit = {
		println(name)
	}

	def test2(like:String): Unit= {
		println(like)
	}

	// 部分参数为隐式参数,需使用*柯里化*的方式
	def test3(name: String)(implicit age: Int) : Unit = {
		println(name + ":" + age)
	}

	def main(args: Array [String]): Unit ={
		test(name=2)   // 可以附带默认值
		// test
		test()    // 正确写法。参数是隐式参数,可以不传参数,系统会自动寻找隐式值
		test2     // 错误写法。参数不是隐士参数,系统无法自动寻找隐式值,因此必须传参数
		
		test3("joy")()
	}
	// 若是在不想传值,在声明隐式参数时设置默认值也可以 
}

9.3 隐式转换函数

隐式转换函数是使用关键字implicit修饰的函数。当Scala运行时,假设如果A类型变量调用了method()这个方法,发现A类型的变量没有method()方法,而B类型有此method()方法,会在作用域中寻找有没有隐式转换函数将A类型转换成B类型,如果有隐式转换函数,那么A类型就可以调用method()这个方法。

9.3.1 注意点

隐式转换函数只与函数的参数类型返回类型有关,与函数名称无关,所以作用域内不能有相同的参数类型返回类型 的不同名称 隐式转换函数。

9.3.2 具体写法

class Bird(name: String) {
	def fly():Unit = {
		println(name + "is flying")
	}
}

class Pig(xname: String) {
	val name = xname
}
object Test_Implicit2 {
	implicit def pigToBird(pig: Pig) : Bird = {
		new Bird(pig.name)
	}
	/**
	 * 转换
	 * a没有b有a想要有,变成b
	 * 对于这样的函数而言,参数a,返回类酗A->B
	 *
	 * @param args
	 */

	def main(args: Array[String]) : Unit = {
		val pig = new Pig("猪")
		pig.fly()
	}
}

9.4 隐式类

使用implicit关键字修饰的类就是隐式类。若一个变量A没有某些方法或者某些变量时,而这个变量A可以调用某些方法或者某些变量时,可以定义一个隐式类,隐式类中定义这些方法或者变量,隐式类中传入A即可。

9.4.1 注意点

  • (1) 隐式类必须定义在类,包对象,伴生对象中。
  • (2) 隐式类的构造必须只有一个参数,同一个类,包对象,伴生对象中不能出现同类型构造的隐式类。

9.4.2 具体方法

class Rabbit(s:String) {
	val name = s
}

object Lesson_Implicitclass {
	implicit class Animal(rabbit:Rabbit) {
		val tp = "Animal"
		def canFly() = {
			println(rabbit.name + "can fly. . .")
		}
	}
	def main(args: Array[String]): Unit = {
		val rabbit = new Rabbit("rabbit")
		rabbit.canFly()
		println(rabbit.tp)
	}
}

第十章 Actor Model

10.1 概念

Actor Model是用来编写并行计算或分布式系统的高层次抽象(类似java中的Thread)让程序员不必为多线程模式下共享锁而烦恼。Actors将状态和行为封装在一个轻量的进程/线程中,但是不和其他Actors分享状态,每个Actors有自己的世界观,当需要和其他Actors交互时,通过发送事件和消息,发送是异步的,非堵塞的(fire-andforget),发送消息后不必等另外Actors回复,也不必暂停,每个Actors有自己的消息队列,进来的消息按先来后到排列,这就有很好的并发策略和可伸缩性,可以建立性能很好的事件驱动系统。

10.2 Actor的特征

  • ActorModel是消息传递模型,基本特征就是消息传递
  • 消息发送是异步的,非阻塞的
  • 消息—旦发送成功,不能修改
  • Actor之间传递时,接收消息的actor自己决定去检查消息, actor不是一直等待,是异步非阻塞的

10.3 具体写法

import scala.actors.Actor

class MyActor extends Actor {
	override def act(): Unit = {
		receive {
			case x:String => println("String")
			case _ => printLn("No!!!!!")
		}
	}
}

object Test_Actor {
	/**
	 * Actor执行顺序
	 * 首先调用start()启动Actor
	 * act()方法随即被执行
	 * 向Actor发送消息进行处理
	 * 
	 * ! 异步发送无返回值
	 * !! 异步发送
	 * !?
	 * @param args
	 */
	def main(args: Array[String]): Unit = {
		val actor = new MyActor
		actor ! "hello"
		actor.start()
	}
}
case Class Message(actor: Actor, msg: String)

class Man extends Actor {
	override def act(): Unit = {
		receive {
			case x:String => {
				printLn(x.msg)
				x.actor ! "hello"
			}
		}
	}
}
class Woman(man: Man) extends Actor {
	override def act(): Unit = {
		while(true) {
			receive {
				case x: String => println("x")
					man ! Message(this, "hi")
			}
		}
	}
}

object Test_Actor2 {
	def main(args: Array[string]): Unit ={
		val man = new Man
		val woman = new Woman(man)
		
		// !跟在谁后面表示这条消息是发给谁的
		woman ! "hello"
		man.start()
		woman.start()
	}
}

声明:本文是学习时记录的笔记,如有侵权请告知删除!
原视频地址:https://www.bilibili.com/video/BV1qf4y1h7rX

 类似资料: