Scala OOP
偏函数
偏函数可以提供了简洁的语法,可以简化函数的定义。配合集合的函数式编程,可以让代码更加优雅。
偏函数被包在大括号内没有match的一组case语句是一个偏函数
偏函数是PartialFunction[A, B]的一个实例
A代表输入参数类型
B代表返回结果类型
实例如下:
//偏函数
def funPartition:PartialFunction[String,Int]={
case "hello"=>1
case "word"=>0
case _=>3
}
val i=funPartition("kb11")
println(i)
def funPart2:PartialFunction[Int,String]={
case 1=>"优秀"
case 2=>"良好"
case 3=>"合格"
case _=>"渣渣"
}
println(funPart2(6))
val arr=Array(1,2,3,4,5)
arr.collect(funPart2).foreach(println)
部分函数
部分应用函数(Partial Applied Function)是缺少部分参数的函数,是一个逻辑上概念。
def sum(x: Int, y: Int, z: Int) = x + y + z, 当调用sum的时候,如果不提供所有的参数,或者只提供某些参数时,比如sum _ , sum(3, _: Int, :Int), sum(: Int, 3, 4), 这样就生成了所谓的部分应用函数。
def sumResult(a:Int,b:Int):Int={
a+b
}
val num1:Int=5
def sum=sumResult(num1,_:Int)
println(sum(3))
println(sumResult(2, 5))
def showMsg(title:String,context: String,height:Double)={
println(title+" "+context+" "+height)
}
showMsg("警告","当前河床水位线",19.8)
val title:String="警告"
val content:String="当前河床水位线"
def showAlarm=showMsg(title,content,_:Double)
showAlarm(20.1)
}
模式匹配
模式匹配是检查某个值(value)是否匹配某一个模式的机制,一个成功的匹配同时会将匹配值解构为其组成部分。它是Java中的switch语句的升级版,同样可以用于替代一系列的 if/else 语句。
一个模式匹配语句包括一个待匹配的值,match关键字,以及至少一个case语句。
import scala.util.Random
val x: Int = Random.nextInt(10)
x match {
case 0 => "zero"
case 1 => "one"
case 2 => "two"
case _ => "other"
}
println(x)
样例类
样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类)
/**示例1 |需求
定义一个Person样例类,包含姓名和年龄成员变量
创建样例类的对象实例("张三"、20),并打印它
*/
package com.robot.scalademo
object _08ObjectDemo {
case class Person(name:String, age:Int)
def main(args: Array[String]): Unit = {
val zhangsan = Person("张三", 20)
println(zhangsan) //Person(张三,20)
}
}
/**示例2 | 可变成员变量
定义一个Person样例类,包含姓名和年龄成员变量
创建样例类的对象实例("张三"、20)
修改张三的年龄为23岁,并打印码
*/
object _02CaseClassDemo {
case class Person(var name:String, var age:Int)
def main(args: Array[String]): Unit = {
val zhangsan = Person("张三", 20)
zhangsan.age = 23
println(zhangsan) //Person(张三,23)
}
}
样例类的方法
当我们定义一个样例类,编译器自动帮助我们实现了以下几个有用的方法:
apply方法
toString方法
equals方法
hashCode方法
copy方法
1 apply方法
apply方法可以让我们快速地使用类名来创建对象。参考以下代码:
case class CasePerson(name:String, age:Int)
object CaseClassDemo {
def main(args: Array[String]): Unit = {
val lisi = CasePerson("李四", 21)
println(lisi.toString)
}
}
2 toString方法
toString返回样例类名称(成员变量1, 成员变量2, 成员变量3…),我们可以更方面查看样例类的成员
case class CasePerson(name:String, age:Int)
object CaseClassDemo {
def main(args: Array[String]): Unit = {
val lisi = CasePerson("李四", 21)
println(lisi.toString)
// 输出:CasePerson(李四,21)
}
}
3 equals方法
样例类自动实现了equals方法,可以直接使用==比较两个样例类是否相等,即所有的成员变量是否相等
示例
创建一个样例类Person,包含姓名、年龄
创建名字年龄分别为"李四", 21的两个对象
比较它们是否相等
val lisi1 = CasePerson("李四", 21)
val lisi2 = CasePerson("李四", 21)
println(lisi1 == lisi2)
// 输出:true
4 hashCode方法
样例类自动实现了hashCode方法,如果所有成员变量的值相同,则hash值相同,只要有一个不一样,则hash值不一样。
package com.robot.scalademo
object _08ObjectDemo {
case class CasePerson(name:String, age:Int)
def main(args: Array[String]): Unit = {
val lisi1 = CasePerson("李四", 21)
val lisi3 = CasePerson("李四", 21)
val lisi2 = CasePerson("李四", 22)
println(lisi1.hashCode()) //718456491
println(lisi3.hashCode()) //718456491
println(lisi2.hashCode()) // 629649205
}
}
5 copy方法
样例类实现了copy方法,可以简单快速创建一个相同的实例对象(不带参数),也可以使用带名参数指定给成员进行重新赋值,创建一个新的样例对象。
示例
创建名字年龄分别为"李四", 21的对象
通过copy拷贝,名字为"王五"的对象
package com.robot.scalademo
object _08ObjectDemo {
case class CasePerson(name:String, age:Int)
def main(args: Array[String]): Unit = {
val lisi1 = CasePerson("李四", 21)
val wangwu1 = lisi1.copy() //不带参数复制
val wangwu2 = lisi1.copy(name="王五")
println(wangwu1) //CasePerson(李四,21)
println(wangwu2) //CasePerson(王五,21)
}
}
实例
this的作用是可以在主构造器里面,增加多个不同参数的构造器,区别于java
apply的作用是可以不用new 对象的方式直接调用方法,也需要对应添加多个参数不同情况
package zb.kb11
class test1(SchoolName:String,leader:String,teacherNum:Int,address:String){
def this(){
this("北大青鸟","zhangsan",20,"小行路")
}
def this(SchoolName:String){
this(SchoolName,"zhangsan",20,"小行路")
}
def this(SchoolName:String,leader:String){
this(SchoolName,leader,22,"小行路")
}
def this(SchoolName:String,leader:String,teacherNum:Int){
this(SchoolName,leader,teacherNum,"小行路")
}
def showMsg(): Unit ={
println("学习名称为:"+SchoolName+" 学校领导为:"+leader+" 老师编号:"
+teacherNum+" 地址为:"+address)
}
}
object test1 {
def apply(SchoolName: String, leader: String, teacherNum: Int, address: String): test1 = new test1(SchoolName, leader, teacherNum, address)
def apply(SchoolName: String, leader: String, teacherNum: Int): test1 = new test1(SchoolName, leader, teacherNum)
def apply(SchoolName: String, leader: String): test1 = new test1(SchoolName, leader)
def apply(SchoolName: String): test1 = new test1(SchoolName)
def apply(): test1 = new test1()
def showMsg(): Unit ={
println("啥也不是")
}
def main(args: Array[String]): Unit = {
val test2 = test1("nanjing","lisi",50,"andemen")
test2.showMsg()
val test3 = test1()
test3.showMsg()
test1.showMsg()
}
}
接口(混入)
Scala采用trait(特征)来代替接口的概念,类似于java中的 interface+abstract class, scala中称为类 混入/继承 了特质
混入特质 with,被实现的方式不具有传递性
继承特质 extends,使方法具有了传递性
如果类没有明确继承父类,即extends关键字没有被占用 就可以使用extends 但是如已经使用了extends继承了父类 再向混入特质就要用 with关键字了 一个类的声明中只能有一个 extends 但是可以有多个with
继承和特质的区别不在于技术上而在于逻辑上
继承的目的——为了符合继承结构树,表明它是什么;
实现特质的目的——为了混入某些特性
package zb.kb11
abstract class Car {
def brand:String
def engine:String
def laba():Unit={
println("鸣笛")
}
}
trait Type1{ //接口
def wheele:String={
println("四个轮子")
"四个轮子"
}
}
trait Type2{
def fly():Unit={
println("飞上天空")
}
def downSea():Unit={
println("不能下海")
}
}
trait balance{
def balance:String
}
class LingYun extends Car(){
override def brand: String = {
println("凌云汽车")
"凌云汽车"
}
override def engine: String = {
println("电动汽车")
"电动汽车"
}
}
class BMW extends Car with Type1 with Type2 {
override def brand: String = {
println("BMW x6")
return "BMW x6"
}
override def engine: String ={
println("3.0T 涡轮增压")
"3.0T 涡轮增压"
}
}
object CarTest{
def main(args: Array[String]): Unit = {
// val bmw =new BMW
// bmw.brand
// bmw.engine
// bmw.laba()
// bmw.wheele
// bmw.fly()
// bmw.downSea()
//混入特质
val lingyun:LingYun with Type1 with Type2 with balance=new LingYun with Type1 with Type2 with balance {
override def balance: String = {
println("两轮,平衡汽车")
"两轮,平衡汽车"
}
}
lingyun.fly()
lingyun.downSea()
lingyun.engine
lingyun.brand
lingyun.wheele
lingyun.balance
}
}