scala 的模式匹配与类型系统

来源:互联网 发布:mac 系统的 制谱软件 编辑:程序博客网 时间:2024/04/29 21:32

主要内容:

1.     scala模式匹配

2.     scala类型系统


scala模式匹配

scala中的模式匹配与java中的switch-case很类似,但是不同的是java中switch-case只能匹配值,而scala模式匹配更强大,还可以对类型进行匹配,也可以对类进行匹配。

例如:

按值匹配:


这里我们定义了一个按值的模式匹配,传入String类型data,然后对data进行匹配,我们先输入了Hadoop,匹配到,输出ok,然后输入Spark,匹配后输出Wow!,最后输入Flink,未匹配到,输出Something others。这里说明一下,在scala里没有switch,而是有match,以及最后一行的case _表示未匹配到以上情况的其他情况。

模式匹配的格式:

变量 match{

       Case值 => 函数体

       Case值 => 函数体

       Case_  => 函数体

}

在case后可以加上条件判断:


并且可以在匹配时对变量赋值


这里我们用变量name接收了传入的匹配值。并且是自动进行的,这一点非常强大。

 

匹配类型:

语法与值得匹配十分类似。


对集合进行模式匹配

对Array进行匹配:

以上我们对数组进行了匹配,case Array(“Scala”)表示是否传入的数组是只含有Scala的字符数组,case Array(spark,hadoop,flink)表示匹配有三个元素的数组,并将数组的元素赋值给spark,hadoop和flink

Case Array(“Spark”, _*)表示匹配以“Spark”开头的元素。

 

 

 

Case Class(样例类)进行模式匹配,相对于java中的javaBean,用来封装消息,而scala不需要我们手动写get和set方法,会默认把参数设置成val。

在运行时,scala编译器会自动生成其半生对象caseobject的apply方法来接收参数,返回一个caseclass的实例。

这里我们定义了一个case class,case Student(name,score)表示匹配Student类类型,并把Student的类的name,和score赋值给这里的name和score,然后进行调用,case Worker(name,score)类似,这一点很强大,我们在通信中,进行匹配时,就能读取消息的内容。在Spark中有个Operation,在匹配时用Some() 和None进行匹配,Some()表示有值,None表示无内容,比NULL好了很多(Spark中用于消息匹配)。Caseclass 在工作时内部的case object可以帮它生成很多实例。而case object本身就是个实例,全局唯一的。我们可以发现Some()继承自case class,而None继承自case object。

类型参数

Scala中的类型参数,初步看与java中的泛型类似。

首先,我们定义了一个带有类型参数的类Person,然后我们定义了它的一个方法。在创建一个它的实例person,并指定类型参数为String,然后调用person的getContent方法,注意这里调用时传入的参数必须为String类型,因为我们已指定了类型参数String。最后打印出结果。我们也可以指定类型参数为Int型。

所以,我们使用类型参数,可以很好的指定特定值得输入类型,然后基于该类型进行一些操作,增加了程序的健壮性。Spark中的RDD就是这样的。

InstanceOf(a)表示a的类型。

 

很多时候,我们要对类型限定边界,然后确认在内部调用时,他一定有其父类的方法。

上边界 语法格式  <:   指定该类是某个类型的子类或某类型本身

下边界 语法格式  >:   指定该类是某个类型的父类或某类型本身

View Bounds(视图界定):某个类型既不属于上边界也不属于下边界时,

View Bounds可以进行隐式转换,对于某些只有是某个类的子类才能调用的方法时,View Bounds将指定的类型进行隐式转换,判断其是否符合要求的上边界或下边界,那么就可以将指定类型传入而不报错。

View Bounds 语法格式<%   (对类型进行隐式转换)

 

上下文Bounds 语法格式   T:类型           (实际上会存在一个类型[T]的值)在工作时会根据上下文,在上下文中注入隐式值,而且是自动完成的。

例如:

 

在字符串中有种类型是Ordering[String],而整形也有一种类型叫Ordering[Int],在运行时,都会有一个上文的隐式值会传入到我们调用的bigger方法中,如上图,在进行不同类型的操作时,我们调用bigger时没传入参数,它会自动传入一个上下文的隐式值。

 

Manifest Context Bounds 对泛型数组很有用,如果我们指定它是某种类型,那数组内部就必须是该类型。这是数组元素为T,那就需要为类或者值函数定义[T:Manifest],这样才能实例化数组。

 

逆变和协变

Class  Person [+T] 协变:父类和子类之间,如果说父类和子类之间的这种继承关系,即T1继承自T2(Class Person[T1]和class People[T2]),那么在运行时classPerson[T1]类和class People[T2]类也会构成父子关系,协变是T1是T2的父类,那么classPerson[T1]也是class People[T2]的父类。

Class Person [-T]  逆变则相反:T1是T2的父类,那么classPerson[T1]也是class People[T2]的子类。

Dependency[_]相当于Dependency[T],存在类型,可以是各种类型,语法更简洁。

Manifest—>ClassTag(前者演化为后者),T:ClassTag他是个泛型,在编译时我们不知道它的类型,但是在运行是会有具体的类型的匹配,运行时,runtime 会通过reflect反射获取全部的类型信息。



0 0