scala 基础 3

教程 青牛 ⋅ 于 2017-11-28 16:00:25 ⋅ 最后回复由 江南一叶 2022-07-30 13:58:31 ⋅ 8249 阅读

apply 和 unapply 方法
apply方法一般被称为注入方法一般用于伴生对象初始化的操作,apply方法的参数列表不需要和构造函数的参数列表统一
unapply方法常被称为提取方法可以用unapply方法提取相同操作的对象,unapply方法会返回一个Option,其内部生成一个Some对象,这个Some是做相似对象的封装,unapply常被用于模糊匹配
apply方法和unapply方法都被隐式的调用

示例:

class ApplyDemo(val name:String,val age:Int) {
}
object ApplyDemo{
def apply(name:String,age:Int,sex:String): ApplyDemo = new ApplyDemo(name,age)
def unapply(arg: ApplyDemo): Option[(String, Int,String)] = {
if(arg == null){
None
}else{
if(arg.name == "hainiu"){
Some(arg.name,arg.age + 2,"男")
}else if(arg.name == "hainiu1"){
Some(arg.name,arg.age + 2,"女")
}
Some(arg.name,arg.age + 2,"其它")
 }
}
}
object ApplyTest{
def main(args: Array[String]): Unit = {
val applyTest = ApplyDemo("hainiu",1,"")
//匹配
applyTest match {
case ApplyDemo("hainiu",age,sex) => println(s"age:$age,sex:$sex")
case _ => println("no match")
}
 val applyTest1 = ApplyDemo("hainiu1",1,"")
//匹配其它
applyTest1 match{
case ApplyDemo("hainiu1",age,sex) => println(s"age:$age,sex:$sex")
case _ => println("no match")
}
}
}

private关键字
在class前面使用private[包名]代表是包的访问权限,只能指定的包名下才能访问
在包名和构造器的参数列表中间加private是指伴生对象的访问权限,只有伴生对象才能访问
变量前加private,此时该字段成为私有字段,伴生对像能访问
变量前加private[this],此时该字段成为私有字段,伴生对像不能访问
方法前加private,此时该字段成为私有方法,伴生对像能访问
方法前加private[this],此时该字段成为私有方法,伴生对像不能访问

package com.hainiu
private[hainiu] class PrivateDemo private (val sex:String,var other:String){
private val name:String = "hainiu"
private[this] var age:Int = 24
private def action():Unit = {
println(s"name:$name,age:$age")
}
private[this] def action1():Unit = {
println(s"name:$name,age:$age")
}
}
object PrivateDemo{
def main(args: Array[String]): Unit = {
val demo = new PrivateDemo("","")
println(demo.name)
println(demo.action)
}
}
object Test{
def main(args: Array[String]): Unit = {
//    val demo = new PrivateDemo("","")
}
}

特质与抽象类
抽象类:
抽象类与Java相似,只是Java中没有属性的抽象

特质:
可以把特质理解成Java中升级版的接口
在Java中接口不能声明没有值的属性和有实现的方法而Scala可以

重写:
重写与Java相似,只是Java中没有重写属性的概念

特质和抽象类的使用区别:
只能继承一个抽象类,但可以实现多个特质。这点和Java一样

object TraitDemo {
def main(args: Array[String]): Unit = {
val bmw = new Bmw
println(bmw.brand)
println(bmw.run())
println(bmw.action)
println(bmw.energy)
println(bmw.power)
println(bmw.wheels)
}
}
/**
* 抽象类
*/
abstract class Car{
//声明了一个没有赋值的字段
val brand:String
//声明了一个没有实现的方法
def run():String
//声明了一个已实现的方法
def action:String = {
"by car"
}
}
/**
* 特质
*/
trait Type{
//声明一个没有赋值的字段
val energy:String
//声明一个没有实现的方法
val power:String
 //声明一个已实现的方法
val wheels:String={
"have four wheel"
}
}
class Bmw extends Car with Type{
//赋值了抽象类中没有的赋值的属性,可以没有override
val brand: String = "宝马"
//实现了抽象类中没有实现的方法
override def run(): String = "我能跑200迈"
//赋值了特质中没有赋值的属性
override val energy: String = "电"
//实现了特质中没有实现的方法,可以没有override
val power: String = "充电"
//重写了抽象类中的方法,必须得有override
override def action: String = "我能自动驾驶"
//重写了特质中的方法,必须得有override
override val wheels: String = "我有四个轮子"
}

语法注意:当不继承类直接实现一个特质,可以不用with直接用extends,实现多个特质的时候可以用多个with,但是必须先extends第一个特质

trait Type1{
val aaa:String
}
trait Type2{
val bbb:String
}
class benz extends Type{
override val energy: String = _
override val power: String = _
}
class benz1 extends Type with Type1 with Type2{
override val energy: String = _
override val power: String = _
override val aaa: String = _
override val bbb: String = _
}

模式匹配
类似Java中的switch case,但比Java中的强大的多,不仅可以匹配字段串、类、元组、集合等
和Java有一点不同就是匹配不到会摄氏,这个需要注意一下
语法
变量 match{
case "值" => 函数体1
case "值2" => 函数体2
}

字体串匹配

import scala.util.Random
object MatchDemo {
def main(args: Array[String]): Unit = {
val arr = Array("A","B","C","D")
val a = arr(Random.nextInt(arr.length))
println(a)
//匹配上了
a match {
case "A" => println("a")
case "B" => println("b")
case "C" => println("c")
case "D" => println("d")
case _ => println("other")
}
 //没匹配上
"1" match {
case "A" => println("a")
case "B" => println("b")
case "C" => println("c")
case "D" => println("d")
case _ => println("other")
}
}
}

类型匹配

object MatchDemo1{
def main(args: Array[String]): Unit = {
val arr = Array("A",1,1.0,true,1L)
val a = arr(Random.nextInt(arr.length))
println(a)
a match {
case a1:String => println(s"macth string:$a1")
case a2:Int => println(s"match Int:$a2")
case a3:Double => println(s"match Double:$a3")
case a3:Boolean => println(s"match Boolean:$a3")
case a3:Long => println(s"match Long:$a3")
case _:Any => println("other")
}
}
}

数组、元组、集合匹配
元组匹配时case后面的值的个数应与被匹配的元组中数据的个数相同,否报错。
当有多个条件能匹配到时以最先匹配到的条件为准

object MatchDemo2 {
def main(args: Array[String]): Unit = {
val arr = Array(1, 2, 3, 4)
arr match {
case Array(1, x, y) => println(s"x:$x,y:$y")
case Array(_, x, y, d) => println(s"x:$x,y:$y,d:$d")
case _ => println("other")
 }
val tuple = (5, 6, 7)
tuple match {
case (1, a, b) => println(s"case1 a:$a,b:$b")
case (3, a, b) => println(s"case2 a:$a,b:$b")
case (_, x, y) => println(s"case3 a:$x,b:$y")
case _ => println("other")
}
val list = List(7,8,9)
list match {
case 7 :: b :: Nil => println(s"case 1 b:$b")
case List(a,b,c) => println(s"case 2 a:$a,b:$b,c:$c")
case 7 :: 8 :: b :: Nil => println(s"case 3 b:$b")
case _ => println("other")
}
}
}

样例类匹配

object MatchDemo3{
def main(args: Array[String]): Unit = {
val arr = Array(MatchObject1,MatchClass(1),MatchClass2(2,"a"))
arr(Random.nextInt(arr.length)) match{
case MatchClass(a) => println(a)
case aa:MatchClass2 => aa.say
case MatchClass2(a,b) => println(a + b)
case MatchObject1 => println("object")
}
}
}
case class MatchClass(a:Int)
case class MatchClass2(a:Int,c:String){
def say:Unit = {
println(s"say:$c")
}
}
case object MatchObject1

偏函数匹配
PartialFunction[A,B]其中A是方法参数类型,B是方法返回值类型,PartialFunction(偏函数)常用作模式匹配,可以用自定义的方法代替

object MatchDemo4{
def m1:PartialFunction[String,String] = {
case "a" => {println("A");"A"}
case "b" => {println("B");"B"}
case _ => {println("other");"Z"}
}
def m2(name:String):String = {
name match{
case "a" => "A"
case "b" => "B"
case _ => "Z"
}
}
def main(args: Array[String]): Unit = {
println(m1("a"))
println(m2("1"))
}
}
回复帖子,然后刷新页面即可查看隐藏内容

版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-青牛,http://hainiubl.com/topics/209
点赞
成为第一个点赞的人吧 :bowtie:
回复数量: 15
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter