Scala函数对象、隐式、异常

函数对象(lambda表达式)
函数式接口

事实上在java 8中也引入了函数式接口,类似Scala中的函数式对象。例如在Java中定义一个函数式接口:

@FunctionalInterface
public interface GreetingService {
    String sayHello(String name);
}

要求接口中只能有一个方法声明。只有函数式接口才可以使用lambda表达式做匿名类实现。

GreetingService gs = (name) -> "hello"+ name;
        gs.sayHello("zhangsan");

类似的这种写法在java 8的集合stream编程中非常常见。例如

List<String> lines = Arrays.asList("this is a demo", "good good study", "day day up");
        lines.stream()
                .flatMap(line -> Arrays.asList(line.split(" ")).stream())
                .forEach(word-> System.out.println(word+"|"));

在这里插入图片描述
Scala这门语言在lambda编程的灵活性上是java无法媲美的。因为Scala在声明函数式对象(等价java函数式接口)是非常轻松的。

在这里插入图片描述
例如以上案例的GreetingService如果使用Scala声明可以简写为如下:

val sayHello:(String)=>String = (name) => "hello" + name
println(sayHello("zhangsan"))
部分应用函数

在Scala中同样对所有的函数都可以理解为是一个函数对象。例如在Scala中可以将任意一个函数转变成对象。例如如下定义一个sum函数。

def sum(x:Int,y:Int):Int={
	x+y
}

在Scala中可以尝试将一个函数转变成一个对象类型,如下:

scala> def sum(x:Int,y:Int):Int={
     | x+y
     | }
sum: (x: Int, y: Int)Int

scala> var sumFun = sum _
sumFun: (Int, Int) => Int = <function2>

scala> sumFun(1,2)
res0: Int = 3

通常将sumFun成为sum函数的部分应用函数,不难看出sumFun事实上是一个变量。该变量的类型是(Int,Int) => Int通常将该类型称为函数式对象。事实上以上的(Int,Int)=>IntFunction2的变体形式。因为Scala最多支持Funtion0~22中变体形式。例如:

class SumFunction extends ((Int,Int)=>Int){
  override def apply(v1: Int, v2: Int): Int = {
    v1+v2
  }
}

等价写法:
class SumFunction extends Function2[Int,Int,Int]{
  override def apply(v1: Int, v2: Int): Int = {
    v1+v2
  }
}
scala> sumFun.isInstanceOf[(Int,Int)=>Int]
res1: Boolean = true

scala> sumFun.isInstanceOf[Function2[Int,Int,Int]]
res2: Boolean = true

isInstanceOf该方法等价于java中的instanceof关键字。用于判断类型。

PartitalFunction(偏函数)

偏函数主要适用于处理指定类型的参数数据,通常用于集合处理中。定义一个函数,而让它只接受和处理其参数定义域范围内的子集,对于这个参数范围外的参数则抛出异常,这样的函数就是偏函数(顾名思义就是这个函数只处理传入来的部分参数)。

偏函数是个特指其的类型为PartialFunction[A,B],其中接收一个类型为A的参数,返回一个类型为B的结果。

//处理 Int类型参数。并且将参 数值*2
  var pf1:PartialFunction[Any,Int]=new PartialFunction[Any,Int] {
    //是否是用户处理类型
    override def isDefinedAt(x: Any): Boolean = {
      x.isInstanceOf[Int]
    }

    override def apply(v1: Any): Int = {
      v1.asInstanceOf[Int]*2
    }
  }

//等价写法
var pf2:PartialFunction[Any,Int] = {case x:Int => x*2}
val a = Array(1,"a",2,"b",true,3)
    //for(i <- a;if(i.isInstanceOf[Int])) yield i
    a.collect(pf1)
    a.collect(pf2)
隐式值注入/转换
隐式值
object CustomImplicits {
  //声明隐式值
  implicit val a:Int = 1
}
object TestImplicits {
  def main(args: Array[String]): Unit = {
    //引入隐式值
    import  CustomImplicits._
    //获取上下文中的一个Int 隐式值,要求类型唯一
    var b:Int = implicitly[Int]

    println(s"b值:${b}")
  }
}

implicit声明隐式值,implicitly获取隐式值

隐式注入
object CustomImplicits {
  //声明隐式值
  implicit val a:Int = 1
  //隐式值注入
  implicit  val msg:String = "哈喽"
}
object TestImplicits {
  def main(args: Array[String]): Unit = {
    //引入隐式值
    import  CustomImplicits._
    sayHello("zhangsan")
    sayHello("lisi")("hello")
  }
  //柯里化
  def sayHello(name:String)(implicit msg:String):Unit={
    println(s"$msg ~ ${name}")
  }
}

要求上下文环境中,必须有一个String类型隐式值,系统会自动注入

隐式转换(把不兼容改为兼容)
object CustomImplicits {
  //声明隐式值
  implicit val a:Int = 1
  //隐式值注入
  implicit  val msg:String = "哈喽"
  //隐式转换
  implicit def s2d1(s:String):Date={
    val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    sdf.parse(s)
  }
}
object TestImplicits {
  def main(args: Array[String]): Unit = {
    //引入隐式值
    import  CustomImplicits._
    showMeTime(new Date())
    //String --> Date
    showMeTime("2011-12-4 10:20:00")//等价 showMeTime(s2d1("2011-12-4 10:20:00"))

  }
  def showMeTime(date:Date):Unit={
    println("北京时间:"+date.toLocaleString)
  }
}
隐式增强(把不可能变为可能)
object CustomImplicits {
  //隐式增强
  implicit class PigImplicits(pig:Pig){
    def speak():Unit={
      println(s"${pig.name} 说话")
    }
    
    def fly():Unit={
      println(s"${pig.name} 会飞")
    }
  }
}
object TestImplicits {
  def main(args: Array[String]): Unit = {
    //引入隐式值
    import  CustomImplicits._
    val pig1 = new Pig("猪坚强") with Flyable{
      override def fly(): Unit = {
        println(s"$name  会飞了")
      }
    }

    pig1.eat()
    pig1.sleep()
    pig1.fly() //自己飞方法
    pig1.speak() //隐式增强


    val pig2 = new Pig("佩奇")
    pig2.eat()
    pig2.sleep()
    pig2.speak()//隐式增强
    pig2.fly()//隐式增强
  }

}
异常处理
  • Java:区分已检查(必须处理)和未检查(可选)异常、捕获有顺序限制,有小->大
public class JavaTransaction {

    public static void main(String[] args) {
        try {
            throw new IOException("自己抛出的");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ArithmeticException e){
            e.printStackTrace();
        } catch (Throwable e){
            e.printStackTrace();
        } finally {
            System.out.println("最终执行");
        }
    }
}
  • Scala:不区分已检查和未检查异常,按照case顺序进行匹配,符合的就使用。可以不按照顺序
object ScalaTransaction {
  def main(args: Array[String]): Unit = {
    try
      throw new IOException("自己抛出的")
    catch {
      case e: IOException =>
        e.printStackTrace()
      case e: ArithmeticException =>
        e.printStackTrace()
      case e: Throwable =>
        e.printStackTrace()
    } finally System.out.println("最终执行")
  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值