一、Scala的模式匹配
1、Scala的数组的模式匹配
首先举个例子说明
scala> def data(array: Array[String]) {
| array match {
| case Array("Scala") => println("It is Scala")
| case Array(param1, param2, param3) => println(param1 + "--" + param2 + "--" + param3)
| case Array("Spark", _*) => println("Spark...")
| case _ => println("Unknown")
| }
|}
data: (array: Array[String])Unit
上图定义了一个函数,该函数对数组进行了模式匹配,这里要说明下的是:
1)第二个匹配为匹配包含三个元素的数组的情况,这里case后面的Array(param1, param2, param3)为三个参数变量;
2)第三个匹配为匹配以”Spark”元素开始的数组,_*为通配符,表示数组中除了元素Spark外,还会有0个或多个元素。
2、Scala的case class模式匹配
首先举例子:
scala> case class Person(name:String)
defined class Person
scala> Person("Scala")
res4: Person = Person(Scala)
上图通过case class定义了一个Person对象,这个有点类似于Java的bean对象。在这里定义的Person case class对象,编译器会自动构造其伴生对象,上面Person(“Scala”)就是伴生对象的Apply来实例化的一个Person对象,这里还需说明的,”Scala”会作为伴生对象的参数来构建Person对象。
总结:
1)case class就相当于Java中的Bean,我们一般用它来封装消息,case class类中的变量是编译器自动定义val的,也就是说变量时不可改变的。
2)定义的case class类,编译器会自动构建该类的伴生对象,我们在创建对象时Person(“Scala”)就是利用伴生对象的Apply方法来构建的,”Scala”会作为Apply的参数来构建。
二、Scala的类型参数
1、多说无益,举例说明:
scala> class Person[T](val cont : T){
| def getCont(id : T) = id+ "--" +cont
|}
defined class Person
scala> val p = new Person("China")
p: Person[String] = Person@4e647f39
scala> p.getCont("0098")
res5: String = 0098--China
上面代买中定义的泛型类Person,通过中括号来表示泛型,泛型所指示的类型我们用T表示,这个Person的默认构造函数为一个带参数(参数类型为T)的,同时在Person类中,我们也定义了一个getCont方法,并且这个方法也带一个参数(参数类型仍然为T),在创建Person对象时,我们这里new Person是没有指定Person的泛型类型,但是我们传的参数可以知道T为String。
2、泛型,边界
1)上边界
上边界:通过<:来表示,表明所指的泛型的类型为<:后面的类或其子类。
2)下边界
用>:来表示,如:[T>:类0],表示这个泛型所指的类T为“类0”的父类或“类0”本身。
三、Scala的逆变与协变
1、 协变
1.1、原理
定义为C[+T],如果S为A的子类,那么C[S]也为C[A]的子类,那么可以用C[S]来泛化C[A]。
1.2、举例:
首先,我们先定义两个类Father和Sub,Sub为Father的子类,如下实例:
scala> class Father
defined class Father
scala> class Sub extends Father
defined class Sub
然后,我们再定义一个支持协变的类XieBian,如下:
class XieBian[+T]
defined class XieBian
好了,定义好了,我们就来分别用XieBian[Sub]来泛化XieBian[Father],以及用XieBian[Father]来泛化XieBian[Sub],如下:
scala> val temp1 : XieBian[Father] = new XieBian[Sub]
temp1: XieBian[Father] = XieBian@6751335c
scala> val temp2 : XieBian[Sub] = new XieBian[Father]
<console>:14: error: type mismatch;
found : XieBian[Father]
requred : XieBian[Sub]
val temp2:XieBian[Sub] = new XieBian[Father]
^
在上面示例代码中清楚的反应了两种泛化的情况,当我们用XieBian[Sub]来泛化XieBian[Father]可以成功,但是用XieBian[Father]来泛化XieBian[Sub]时,出现类型不匹配错误,根据我们已掌握的知识,子类是可以泛化父类的,所以,我们就知道XieBian[Sub]就是XieBian[Father]的子类。
2、逆变
2.1、原理
我们知道了协变的原理后,其实就可以很清楚的理解逆变的原理了,逆变就是与协变反向的。
也就是说:定义为C[-T],如果S是A的子类,那么C[A]便是C[S]的子类,可以用C[A]来泛化C[S]。
2.2、举个实例
首先,我们先定义一个支持逆变的类NiBian,如下代码:
scala> class NiBian[-T]
defined class NiBian
然后,我们就开始分别用NiBian[Father]来泛化NiBian[Sub],以及用NiBian[Sub]来泛化NiBian[Father],如下:
scala> val temp3 : NiBian[Father] = new NiBian[Sub]
<console>:14: error: type mismatch;
found : NiBian[Sub]
required: NiBian[Father]
val temp3 : NiBian[Father] = new NiBian[Sub]
^
scala> val temp4 : NiBian[Sub] = new NiBian[Father]
temp4: NiBian[Sub] = NiBian@439f34f6
上面两种泛化示例中,很清楚的表名NiBian[Father]可以泛化NiBian[Sub],反之却不可以,那么我们就知道了NiBian[Father]是NiBian[Sub]的子类。