Scala的模式匹配,以及逆变、协变等

一、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]的子类。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值