主要内容:
1. scala模式匹配
2. 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反射获取全部的类型信息。