Scala基础手稿

一、Scala的数据类型
Byte: 8位有符号补码整数。数值区间为 -128 到 127
Short:16位有符号补码整数。数值区间为 -32768 到 32767
Int: 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Long: 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
Float: 32 位, IEEE 754 标准的单精度浮点数
Double :64 位 IEEE 754 标准的双精度浮点数
Char :16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
String :字符序列
Boolean:true或false
Unit :表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Null null 或空引用
Nothing:Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。
Any :Any是所有其他类的超类
AnyRef:AnyRef类是Scala里所有引用类(reference class)的基类
二、变量声明
在 Scala 中,使用关键词 “var” 声明变量,使用关键词 “val” 声明常量。
变量的类型在变量名之后等号之前声明:var VariableName : DataType [= Initial Value]
在 Scala 中声明变量和常量不一定要指明数据类型,在没有指明数据类型的情况下,其数据类型是通过变量或常量的初始值 推断出来的。
所以,如果在没有指明数据类型的情况下声明变量或常量必须要给出其初始值,否则将会报错。
Scala字符串前加s使用 : S c a l a 中 基 础 的 字 符 串 插 值 就 是 在 字 符 串 前 加 字 幕 ‘ s ’ , 然 后 在 字 符 串 中 放 入 变 量 , 每 个 变 量 都 应 以 ‘ : Scala中基础的字符串插值就是在字符串前加字幕‘s’,然后在字符串中放入变量,每个变量都应 以‘ Scalas’开头。字符串前加字母‘s’时,其实是在创建一个处理字符串字面量。实际调用的是 StringContext 中的 s 方法。
给出一个小案例ruxia:

object SDemo {
  def main(args:Array[String])={
    var name = "王五"
    var age = 18
    println(s"name=$name,age=$age")
  }
}
结果:王五 18

三、Scala循环

1for 循环
	    //Scala 语言中 for 循环的语法:
		for( var x <- Range ){
           statement(s);
        }
		//Range 可以是一个数字区间表示 i to j ,或者 i until j。左箭头 <- 用于为变量 x 赋值
		//i to j:包括i和j
		//i until j 不包括j
	//在 for 循环 中你可以使用分号 (;) 来设置多个区间,它将迭代给定区间所有的可能值。以下实例演示了两个区间的循环实例:
		for(i<- 4 to 8;j<-1 until 3){
           println(j) 
           println(i)
        }
		
		//for 循环过滤
        //Scala 可以使用一个或多个 if 语句来过滤一些元素。
		for( var x <- List
             if condition1; if condition2...){
             statement(s);
		}
			
		
        //for 使用 yield
        //你可以将 for 循环的返回值作为一个变量存储。语法格式如下:
        var a = 0;
        val numList = List(1,2,3,4,5,6,7,8,9,10);

        // for 循环
        var retVal = for{ a <- numList
                        if a != 3; if a < 8
                      }yield a
        for(i<- retVal){
		    println(i)
		}
2、Scala while 循环
	while(condition)
    {
        statement(s);
    }

    var c = 1
    while(c<10){
      print(c)
      c+=1
    }

3、Scala 方法与函数
Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。
<1>函数可作为一个参数传入到方法中,而方法不行。
<2>在Scala中无法直接操作方法,如果要操作方法,必须先将其转换成函数。有两种方法可以将方法转换成函数:
val f1 = m _
在方法名称m后面紧跟一个空格和下划线告诉编译器将方法m转换成函数,而不是要调用这个方法。
val f1: (Int) => Int = m
也可以显示地告诉编译器需要将方法转换成函数
<3>函数必须要有参数列表,而方法可以没有参数列表
val fn =()=> 100 //这个函数编译能通过
val fn = => 100 //这个函数不能通过,因为没有参数
scala> def m1(x:Int) = x+3
m1: (x: Int)Int    
def m1(x: Int) = x+3就是一个简单的method的定义。signature中m1: (x: Int)Int 表示method m1有一个参数Int型参数x,返回值是Int型。
scala> val f1 = (x: Int) => x+3
f1: Int => Int =
val f1 = (x: Int) => x+3则是function的定义,解析器的signature中f1: Int => Int = 表示function f1的method体接受一个Int型的参数,输出结果的类型是Int型。

Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。
Scala 中使用 val 语句可以定义函数,def 语句定义方法。
	class Test{
          def m(x: Int) = x + 3
          val f = (x: Int) => x + 3
    }
	方法定义
	def functionName ([参数列表]) : [return type] = {
        function body
        return [expr]
    }

4、Scala 函数传名调用(call-by-name)
Scala的解释器在解析函数参数(function arguments)时有两种方式:
1)传值调用(call-by-value):先计算参数表达式的值,再应用到函数内部;
2)传名调用(call-by-name):将未计算的参数表达式直接应用到函数内部

       object Test {
           def main(args: Array[String]) {
                delayed(time());
           }
        
           def time() = {
              println("获取时间,单位为纳秒")
              System.nanoTime
           }
           def delayed( t: => Long ) = {
              println("在 delayed 方法内")
              println("参数: " + t)
           }
        }
以上实例中我们声明了 delayed 方法, 该方法在变量名和变量类型使用 => 符号来设置传名调用。

5、高阶函数
函数可以作为方法的参数进行传递和调用
占位符:占位符指的是scala中的下划线_ ,可以用它当作一个或多个参数来使
使用_占位符的前提要求:每个参数在函数仅出现一次
使用下划线时,如果类型可以自动推断出,则不用声明类型。如果无法自动推断类型,则在下划线后自己来显示声明类型即可。

6、Scala 字符串
    在 Scala 中,String 是一个不可变的对象,所以该对象不可被修改。这就意味着你如果修改字符串就会产生一个新的字符串对象。
    字符串长度:length()
    字符串连接:concat()
    同样你也可以使用加号(+)来连接:
    char charAt(int index)
    返回指定位置的字符
    int compareTo(String anotherString)
    按字典顺序比较两个字符串
    int compareToIgnoreCase(String str)
    按字典顺序比较两个字符串,不考虑大小写
    boolean contentEquals(StringBuffer sb)
    将此字符串与指定的 StringBuffer 比较。
    static String copyValueOf(char[] data)
    返回指定数组中表示该字符序列的 String
    boolean endsWith(String suffix)
    测试此字符串是否以指定的后缀结束
    boolean equals(Object anObject)
    将此字符串与指定的对象比较
    boolean equalsIgnoreCase(String anotherString)
    将此 String 与另一个 String 比较,不考虑大小写
	byte getBytes()
    使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
	byte[] getBytes(String charsetName
    使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
	boolean matches(String regex)
    告知此字符串是否匹配给定的正则表达式	
	String replace(char oldChar, char newChar)
    返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的
	String replaceAll(String regex, String replacement
    使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串	
	String substring(int beginIndex, int endIndex)
    返回一个新字符串,它是此字符串的一个子字符串	
	String trim()
    删除指定字符串的首尾空白符				
    boolean startsWith(String prefix)
    测试此字符串是否以指定的前缀开始	
    boolean startsWith(String prefix, int toffset)
    测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
    String[] split(String regex)
    根据给定正则表达式的匹配拆分此字符串
	
7、Scala 数组
    注:对于数组的使用,若想调用数组提供的方法,我们需要使用 import Array._ 引入包
    以下是 Scala 数组声明的语法格式:
    定长数组申明:
	var z:Array[String] = new Array[String](3) 或者var z = new Array[String](3)
	变长数组:
	 val val3=scala.collection.mutable.ArrayBuffer[Int](3)
     或val val3=ArrayBuffer[Int]()
     
	合并数组
    以下实例中,我们使用 concat() 方法来合并两个数组,concat() 方法中接受多个数组参数:
    var myList1 = Array(1.9, 2.9, 3.4, 3.5)
    var myList2 = Array(8.9, 7.9, 0.4, 1.5)
    var myList3 =  concat( myList1, myList2) 
    数组的赋值和取值:
    赋值方式一:用for循环为数组var1赋值
        for(i<-0 to myList1.length-1){
             myList1(i)=i
        }
    赋值方式二:为变长数组赋值,注意:变长数组提供了append方法用于赋值,并且隐式的改变数组长度
	for(i<-1 to 10){
          val3.append(i)
    }
   取值方式一:根据数组下标取值
           myList2 (0);myList2 (1);myList2 (2);
   取值方式二:利用for循环取值
           for(i<-myList2 )println(i)
   取值方式三:用高阶函数 foreach
           var1.foreach{x=>println(x)}
	创建区间数组
    以下实例中,我们使用了 range() 方法来生成一个区间范围内的数组。range() 方法最后一个参数为步长,默认为 1:
	var myList1 = range(10, 20, 2)
	def empty[T]: Array[T]
    返回长度为 0 的数组
	def iterate[T]( start: T, len: Int )( f: (T) => T ): Array[T]
    返回指定长度数组,每个数组元素为指定函数的返回值。
	Array.iterate(0,3)(a=>a)
	res1: Array[Int] = Array(0, 1, 2)
	def tabulate[T]( n: Int )(f: (Int)=> T): Array[T]
    返回指定长度数组,每个数组元素为指定函数的返回值,默认从 0 开始。
    for(y<-Array.tabulate(3)(a => a))
    print(y)
	012
	sum 求和
	min 最小值
	max 最大值
	quickSort 排序
	
8、Scala Collection
    Scala 集合分为不可变(immutable)的集合和可变(mutable)的集合。
    可变集合可以在适当的地方被更新或扩展。这意味着你可以修改,添加,移除一个集合的元素。
    而不可变集合类,相比之下,永远不会改变。不过,你仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,
    同时使原来的集合不发生改变。
    (1)Scala List(列表)
    List的特征是其元素以线性方式存储,集合中可以存放重复对象。列表是不可变的,值一旦被定义了就不能改变	
    val site: List[String] = List("Runoob", "Google", "Baidu")
    构造列表的两个基本单位是 Nil 和 ::
    Nil 也可以表示为一个空列表。
    val num = 1::2::3::Nil
    列表基本操作
    Scala列表有三个基本操作:
    head 返回列表第一个元素
    tail 返回一个列表,包含除了第一元素之外的其他元素
    isEmpty 在列表为空时返回true
    apply	根据下标获取列表元素值
    num.apply(1)
    +:和:+用于向列表里添加元素
    val num = 1::2::3::Nil 
    val ln=num :+9
    val lm = 9 +: num
    连接列表
    你可以使用 ::: 运算符
    或 List.concat() 方法来连接两个或多个列表
    val l = nums:::num
    reverse用于将列表的顺序反转
    l.reverse
    
    contains	查看列表是否包含某个元素
    contains(elem: Any): Boolean	
    distinct   	元素去重
    drop	drop(n: Int): List[A] 丢弃前n个元素,并返回新列表
    dropRight(n)	丢弃尾部的n个元素
    foreach	foreach(f: (A) => Unit): Unit 将函数应用到列表的所有元素
    mkString	mkString: String 列表所有元素作为字符串显示
    toString	toString(): String列表转换为字符串
    sorted	sorted[B >: A]: List[A]列表排序,默认升序
    intersect	intersect(that: Seq[A]): List[A]计算多个集合的交集

9、Scala Set(集合)
Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的。Scala 集合分为可变的和不可变的集合。
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。
Scala集合有三个基本操作:
    1)head 返回集合第一个元素
    2)tail 返回一个集合,包含除了第一元素之外的其他元素
    3)isEmpty 在集合为空时返回true
	连接集合: 你可以使用 ++ 运算符来连接两个集合。如果元素有重复的就会移除重复的元素。
	            val s1= Set(1,2,3,4)
                val s2= Set(4,5,6,7)
                val s3= s1++s2
	交集:你可以使用 Set.& 方法或 Set.intersect 方法来查看两个集合的交集元素。
	            val s4= s1.&(s2)
	            val s5=s1.intersect(s2)
				
		
    def +(elem: A): Set[A]
    为集合添加新元素x,并创建一个新的集合,除非元素已存在
	
	def -(elem: A): Set[A]
    移除集合中的元素,并创建一个新的集合
	
	def foreach(f: (A) => Unit): Unit
    将函数应用到不可变集合的所有元素

    def map[B](f: (A) => B): immutable.Set[B]
    通过给定的方法将所有元素重新计算
    			
    def filter(p: (A) => Boolean): Set[A]
    输出符合指定条件的所有不可变集合元素。
	
	def dropWhile(p: (A) => Boolean): Set[A]
    从左向右丢弃元素,直到条件p不成立
10、Scala 元组
    与列表一样,元组也是不可变的,但与列表不同的是元组可以包含不同类型的元素。元组的值是通过将单个的值包含在圆括号中构成的。例如:	
	val t = (1, 3.14, "Fred")  
	元组的实际类型取决于它的元素的类型
	目前 Scala 支持的元组最大长度为 22。对于更大长度你可以使用集合,或者扩展元组。访问元组的元素可以通过数字索引,如下一个元组:
	val t = (4,3,2,1)
	我们可以使用 t._1 访问第一个元素, t._2 访问第二个元素
    迭代元组
    你可以使用 Tuple.productIterator() 方法来迭代输出元组的所有元素:
    val t = (4,3,2,1)
    t.productIterator.foreach{ i =>println("Value = " + i )}		
	
11、Scala Map(映射)
    Map 有两种类型,可变与不可变,区别在于可变对象可以修改它,而不可变对象不可以。
    默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map 类
	定义 Map 时,需要为键值对定义类型。如果需要添加 key-value 对,可以使用 + 号
	Map 的分类和定义:
	(1)不可变Map
    var m1=Map("james"->20,"luce"->22);
	val map1 = scala.collection.immutable.Map("wyc"->30,"tele"->20,"yeye"->100,"haha"->1000);
    val map2=map1+("6"->36)
	(2)可变Map
	//指定泛型,如果不指定scala会根据类型自动判断
    var m3=scala.collection.mutable.Map[String,Int]();
	
	(3)不可变Map的使用
	//根据Key获取value 如果key不存在的话会抛出异常
    m1("james");
     
    //等同于m1("james") 如果key不存在的话会 返回None
    m1.get("james");
     
    //给key 设置一个默认值,如果key 不存在就设置为20 不至于抛出异常
    m1.getOrElse("tom", 20)
     
    //获取所有的key
    m1.keys
     
    //获取所有的value
    m1.values
	
	可变Map的操作
	
	(4)可变Map的操作
	//可变Map
    var m2=scala.collection.mutable.Map("james"->20,"luce"->22);
     
    //产生一个新的对象,不会动态增加
    m2+("lili"->18)
     
    //不产生新对象直接在m2 中增加对象
    m2+=("lili"->18);
	
	(5)遍历集合
	遍历所有的key 和value  格式for((k,v)<-x){....}
	//可变Map
    var m2=scala.collection.mutable.Map("james"->20,"luce"->22);
	
	//遍历Key 和Value
    for((k,v)<-m2){println("key is"+k+" value is"+v)}
	
	
	单独的遍历Key 或者value   for((k,_)<-x){}  for((_,v)<-x){}
	//只遍历所有的key value 省略
    for((k,_)<-m2) println("key is "+k)
 
    //只遍历所有的value key省略
    for((_,v)<-m2) println("value is"+v)
	
	
12、Scala Option(选项,用在定义函数的返回类型)
    Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。Option[T] 是一个类型为 T 的可选值的容器:如果值存在, Option[T] 就是一个 Some[T],如果不存在,Option[T] 就是对象 None 。
    Option 有两个子类别,一个是 Some,一个是 None,当他回传 Some 的时候,代表这个函式成功地给了你一个 String,而你可以透过 get() 这个函式拿到那个 String,如果他返回的是 None,则代表没有字符串可以给你。

13、Scala Iterator(迭代器)
    Scala Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。
    迭代器 it 的两个基本操作是 next 和 hasNext。
    可以使用while或者for来逐个返回元素		
	
	//定义一个列表,包含 1,2,3,4,5  
    val a = List(1,2,3,4,5)
    //使用while循环和迭代器,遍历打印该列表
    val ite = a.iterator
    while(ite.hasNext) {
          println(ite.next)
        }
    //使用for 表达式和迭代器,遍历打印该列表
    for (a <- a.iterator ) println(a)
	
14、重要的高阶函数
     	(1)map:映射,把一个集合转换为另外一个集合。集合中元素个数不变
	    val l: List[Int] = List(1, 2, 3, 4)
		val l2=l.map { x => x+1 }
	    for(j<-l2)
            println(j)

        (2)partition:拆分,将一个集合按一个布尔值分成两个集合,满足条件的一个集合,其他另外一个集合 ,返回类型是Tuple
	    val l:List[Int]=List(1,2,3,4,5,6)
		l.partition { x => x%2==0}
		res5: (List[Int], List[Int]) = (List(2, 4, 6),List(1, 3, 5))
		
		
		(3)filter:过滤
		val l3=l.filter { x => x%4==0}
		
		
		(4)reduce:归约,reduce的过程:将上次的运行结果和下一个值进行运算函数接收两个参数 => 返回一个值
		val s=l.reduce((x,y)=>x+y)
		
		(5)groupBy	按指定规则做聚合,最后将结果返回到一个map映射里
		var v2 = List(("北京",1),("上海",3),("天津",2), ("北京",2), ("北京",1), ("上海",4), ("北京",2))
        v2.groupBy(x=>x._1)
        scala.collection.immutable.Map[String,List[(String, Int)]] = Map(上海 -> List((上海,3), (上海,4)), 北京 -> List(( 北京,1), (北京,2), (北京,1), (北京,2)), 天津 -> List((天津,2)))
	    
		(6)mapValues	对map集合中的值做映射。注:只有map类型有
		
Scala的类(class):
        1)scala中的类同样通过class来进行申明
        2)scala中的同类样可以有成员变量和成员方法
		3)scala中的类也可以通过new关键字来创建对象
		
		Scala类的定义
		scala同Java一样也可以定义很多构造器但分为主构造器和辅助构造器
		scala中变量(var)声明时需要指定初始值
		scala中的类不需要明确声明一个构造器,而是直接将构造参数通过构造参数列表声明为类的一部分。
		而直接写在类的体中的既不是类的成员变量也不是成员函数的部分,会自动收集为构造函数的体,。如下执行结果就会是:Tom 18
		
		class Demo(lk:String){
              var Nm=""
              var Ag=0
              def spaek(Nm:String,Ag:Int):Unit={
                print(Nm+Ag)
              }
              
              print("Tom")
              print(18) 
			}  
      
        val p = new Demo("Jone",16);
        Tom 18
		
		辅助构造器
		1)Scala的辅助构造器定义开始于def this()【辅助构造器的名称为this】
		2)Scala里每个辅助构造器的第一个动作都是调用同类的构造器。【每个辅助构造器都必须以一个对先前已经定义的其他构造器调用先开始】
class Person(Nam:String,Age:Int) {
                var name = Nam
                var age = Age
                def this(name:String){
                  this(name,0)  //调用主构造器
                  this.name = name
                  println(this.name)
                }
                
                def this(age:Int){
                  this("")//调用的前一个辅助构造器
                  this.age = age
                  println(this.age)
                }
                print("hello I'm"+name+"***********"+age)
            }
Scala包的引用
import
scala中的import时可以指的是对象和包
scala默认会自动引入如下三个包下的所有内容
java.lang //java中的通用类
scala._ //scala提供的通用类 主要是基本类型除了String
Predef._ //提供了单例对象 以及一些常用方法 print println

Scala中类的继承:
    1、重写一个非抽象方法必须使用override修饰符。
    2、在子类中只有主构造函数才可以往基类(父类)的构造函数里写参数。
    3、在子类中重写超类的抽象方法时,你不需要使用override关键字。
    
	如果我们想在子类中定义和父类相同的属性(覆盖override)则需要注意父类属性的参数的修饰符必须为val(var 也不行), 
	否者会报错,在Scala中属性覆盖针对不易变的属性,子类必须加上override val XXX:Tpye
	如果父类中有了非val的属性,我们的子类直接就可以在创建对象的时候,默认的构造中可以传入对应的属性值,并且使用该对象也可以访问的到,所以针对于非val的属性没必要override。
	而val修饰符在编译后的JAVA文件中是final修饰 是最终变量不可变,所以该值在子类中想引用这个变量并且想改变他的值,则需要override val,想想Scala这样设计也是挺合理的
package firstday

        abstract class Teacher(Nam:String) {
         var Nm:String=Nam
         def speak();
         def sleep(){
           print("hello I'm sleeping")
         }
        }
 		
		
		package firstday

        class JavaTeacher(Nam:String,Age:Int) extends Teacher(Nam){
          var age:Int=Age
          override def speak():Unit={
            println("hello I am"+ " "+Nam,"and I am "+age+" years old")
            super.sleep
          }
        }
		
		object Test {
          def main(args:Array[String]):Unit={
            //val l :Location = new Location(1,2,3)
            //l.move(1, 2, 3)
            val jt= new JavaTeacher("Jone",18);
            jt.speak()
          }
        }
		
类和单例对象的区别:
    单例对象(object)不接受参数,而类可以。
    由于没法用new实例化单例对象,也就没有任何手段来向它传参。
    每个单例对象都是通过一个静态变量引用合成类的实例来实现的,因此单例对象跟Java静态成员是一致的。单例对象在有代码首次访问时才能被初始化。 		
	scala的object相当于java中的static类
    定义在object中的字段或者方法也是具有static特性的,可以直接拿来用不用new。(Scala中没有static关键字)main方法必须位于object中而不能在class中
	当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:
	companion class。类和它的伴生对象可以互相访问其私有成员。
package firstday

        class Student {
          var Nm :String=""
          var Age:Int=0
          var ID:String=""
          var score:Float= 0.0f
          def this(name:String){
            this()
            this.Nm=name
          }
          
          def this(score:Float){
            this("")
            this.score = score
          }
          
        }
        
        object Student{
          def show():Float={
            val s = new Student(97.5f)
            s.score
          }
          def main(args:Array[String]):Unit={
            val f = show()
            print(f)
          }
        }
Trait特质
1)特质相当于java中的接口,java中称为类实现了接口,scala中称为混入了特质。
2)和java中的接口不同的是,scala中的特质可以包含具有方法体的方法。
3)在类中可以通过extends 或 with 关键字来让类混入特质,如果类没有明确继承父类,extends关键字没有被占用就可以使用extends。
  但是如已经使用了extends显示的继承了父类,再向混入特质就要用with关键字了。
 package firstday
	
	trait Persons {
      def eat(food:String)
      def speak(lag:String)
    }	

    class Teachers extends Persons{
      override def eat(food:String):Unit={
        println("hello I like eat"+food)
      }
      
      override def speak(lag:String):Unit={
        println("I Can speak"+lag)
      }
    }	
lazy:
正常情况下通过val 和 var定义的量都会直接分配空间,即使这个量要在很久以后才使用,这样就会造成内存空间白白被占用。这种情况下可以加上lazy关键字,
延后变量/常量赋值的位置。这样直到后续真正用到这个量时才真正开辟空间赋值,减少了内存的浪费。	
	
val name = "zhang"//直接分配空间 即使一时半会用不到	
lazy val name = "zhang"//并不会立即分配空间直到后续用到了才会分配	

Scala样例类 case class
    1)定义样例类:只要在声明类时 在class关键字前加上case关键字 这个类就成为了样例类
      样例类必须要显示的声明一个主构造器。
	2)当样例类声明一个主构造器后,会默认隐式的声明一个空构造器
    3)样例类默认实现序列化接口
    4)样例类默认自动覆盖 toString equals hashCode方法 		
	5)样例类不需要new可以直接生成对象
object CaseDemo {
  def main(args: Array[String]): Unit = {
    //定义样例类
    //构造函数的参数默认是public
    case class Message( var sender:String,recipient:String ,body:String)
      //创建样例类的对象
      val messagel=Message("Jerry","Tom","Hello")
      println("sender:"+messagel.sender)
      println("recipient:"+messagel.recipient)
      messagel.sender="Bob"//sender使用var修饰时可以输出
      println("sender2:"+messagel.sender)
      //messagel.recipient="sss"//recipient默认使用val修饰
  }
}
普通类只有在伴生对象中定义apply和unapply方法才能够利用伴生对象的方式创建对象和模式匹配。
/**
 * apply方法通常称为注入方法,在伴生对象中做一些初始化操作
 * apply方法的参数列表不需要和构造器的参数列表统一
 * unapply方法通常称为提取方法,使用unapply方法提取固定数量的参数来进行模式匹配
 * unapply方法会返回一个序列(Option),内部产生一个Some对象,Some对象存放一些值
 * apply方法和unapply方法会被隐式的调用
 * @param name
 * @param age
 * @param faceValue
 */
	package firstday

    class ApplyDemo(val name:String,var age:Int,var faceValue:Int) {
      
    }
    
    object ApplyDemo{
      //注入方法
      def apply(name:String,age:Int,gender:Int,faceValue:Int):ApplyDemo={
        new ApplyDemo(name,age,faceValue)
      }
      //提取方法:提取固定数量的参数
      def unapply(applyDemo:ApplyDemo):Option[(String,Int,Int)]={
        if(applyDemo==null){
          None
        }else{
          Some(applyDemo.name,applyDemo.age,applyDemo.faceValue)
        }
      }
    }
		
		
	object Test {
      def main(args:Array[String]):Unit={
        val applyTest=ApplyDemo("ning",23,0,90)//没有用new,调用了ApplyDemo的apply方法
        println(s"applyTest_name:$applyTest.name")
        applyTest match{
          case ApplyDemo("ning",age,faceValue)=>println(s"age:$age")
          case _=>println("nothing")
        }
        
      }
    }	
	
模式匹配和样例类:
1)模式匹配
Scala是没有Java中的switch case语法的,相对应的,Scala提供了更加强大的match case语法,即模式匹配,来替代switch case,match case也被称为模式匹配

match case的语法如下:
变量 match { case 值 => 代码 }
如果值为下划线“_”,则代表了不满足以上所有情况下的默认情况如何处理。
此外,match case中,只要一个case分支满足并处理了,就不会继续判断下一个case分支了。

2)样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值