scala基础5⃣️高阶函数

来源:互联网 发布:融资知乎 编辑:程序博客网 时间:2024/06/06 03:46
========================scala函数========================================

Scala函数可以直接赋值给变量,语法规定,将函数赋值给变量时,必须在函数名后面加上空格和下划线

def sayHello(name: String) = { println("Hello, " + name) }
val sayHelloFunc = sayHello _
sayHelloFunc("leo")


** 匿名函数的语法: (参数名: 参数类型) => 函数体

def sayHelloFunc = (name: String) => println("Hello, " + name)
sayHelloFunc("leo")

-------------------—/高阶函数/---------------------------------------

//函数作为参数

val sayHelloFunc = (name: String) => println("Hello, " + name)
def greeting(func: (String) => Unit, name: String) { func(name) }
greeting(sayHelloFunc, "leo")

//函数作为返回值
def getGreetingFunc(msg: String) = (name: String) => println(msg + ", " + name)
//val greetingFunc = getGreetingFunc("hello")
//greetingFunc("张三")
getGreetingFunc("hello")("张三")

-------------------------------自动类型推断---------------------

def greeting(func: (String) => Unit, name: String) { func(name) }


greeting((name: String) => println("Hello, " + name), "leo")
//高阶函数可以自动推断出参数类型
greeting((name) => println("Hello, " + name), "leo")
//对于只有一个参数的函数,可以省去其小括号
greeting(name => println("Hello, " + name), "leo")
//见下
greeting(println(_), "leo")
//greeting(println("Hello, " + _), "leo")  //错误,此种语法不是万能的

-------------

def double(x :Int,func: (Int) => Int) = { func(x) }
//如果仅有的一个参数在右侧的函数体内只使用一次,则还可以将接收参数省略,并且将参数用_来替代

println(double(5, 2 * _ ))  //正确,x=>2*x







------------------------/常用高阶函数/------------------

//依次处理每个元素,并返回处理后的元素的集合
for(x <- Array(1, 2, 3, 4, 5).map(2 * _))
  print(x+" ")

println("a"*3)
//对传入的每个元素进行处理,但是没有返回值
(1 to 9).map("*" * _).foreach(println _) //println后面的_也可以省略

//对每个元素都进行判定,结果为true则保留,否则删除
for(x <- (1 to 10).filter(_ % 2 == 0))
  print(x+" ")

//从左侧开始,进行reduce操作,即先对元素1和元素2进行处理,然后将结果与元素3进行处理,依次类推...
println((1 to 10).reduceLeft( _ + _ ))//左边开始计算,第一计算的的结果输出到下个计算数据的左边
println((1 to 10).reduceRight( _ - _ ))//右边开始计算,倒数第二个减去倒数第一个,得出的结果放到下个计算数据的右边。

===================隐式转换============================================

** 只要在程序可见范围内定义了隐式转换函数,就会被Scala自动调用
** 隐式转换函数的名字可以任意,建议命名为“xxx2yyy”的形式
** 以implicit开头,而且最好定义函数返回类型

def main(args:Array[String]): Unit ={
    class Student(val name: String)
    class Older(val name: String)
    class SpecialPerson(val name: String)

    implicit def object2SpecialPerson (obj: Object): SpecialPerson = {
      if (obj.getClass == classOf[Student]) {
        val stu = obj.asInstanceOf[Student];
        new SpecialPerson(stu.name)
      }
      else if (obj.getClass == classOf[Older]) {
        val older = obj.asInstanceOf[Older]
        new SpecialPerson(older.name)
      }
      else null
    }


    var ticketNumber = 0
    def buySpecialTicket(p: SpecialPerson) = {
      ticketNumber += 1
      "T-" + ticketNumber
    }

    val a=new Student("aaa")
    println(buySpecialTicket(a))
    val b=new Older("bbb")
    println(buySpecialTicket(b))
}

--------------------------隐式转换-----------------

** 隐式转换的强大之处就是可以增强现有类的功能
** 如果隐式转换函数不在可见范围内,那就必须使用import来导入,如:import xxx._

class Man(val name: String)
class Superman(val name: String) {
  def emitLaser = println("emit a laster!")
}

implicit def man2superman(man: Man): Superman = new Superman(man.name)

val leo = new Man("leo")
leo.emitLaser
 
** Scala什么时候会进行隐式转换?
1 调用某个函数,但传入参数的类型与函数定义的参数类型不匹配(函数)
2 调用某个方法,虽然该类有这个方法,但给方法传入的参数类型,与方法定义的参数类型不匹配(方法)
3 使用某个对象,调用某个方法,但这个方法并不存在于该类时

 
------------------------隐式参数---------------------

** 在函数或方法中,用implicit来修饰的参数即为隐式参数
** Scala会尝试找到一个对应类型的、用implicit修饰的对象,即隐式值,并将其作为参数自动注入
** Scala会在两个范围内查找:一个是当前作用域内可见的val或var定义的隐式变量
** 另一个是隐式参数类型的伴生对象内的隐式值
 
class SignPen {
  def write(content: String) = println(content)
}
implicit val pen = new SignPen

def signForExam(name: String) (implicit signPen: SignPen) {
  signPen.write(name + " come to exam in time.")
}
signForExam("aaa")

==========================特质triat================================

** triat与Java中的接口非常类似,在triat中可以定义抽象方法
** 使用extends关键字继承trait
** Scala不支持类的多继承,但支持trait多继承,使用with关键字即可
** 类继承trait后,必须实现其中的抽象方法
   
trait HelloTrait {
  def sayHello(name: String)
}
trait MakeFriendsTrait {
  def makeFriends(p: Person)

}
class Person(val name: String) extends HelloTrait with MakeFriendsTrait {
  def sayHello(name: String) = println("Hello, " + name)
  def makeFriends(p: Person) = println("my name: " + name + ", your name: " + p.name)
}

def main(args:Array[String]): Unit ={
  val a=new Person("aaa")
  a.sayHello("bbb")
  val b=new Person("bbb")
  a.makeFriends(b)
}

----------------------------------

** triat中可以定义具体字段,也可以定义抽象字段
** triat中可以定义抽象方法,也可以定义具体方法
** trait中的具体方法可以基于抽象字段来编写

trait T{
  val x=10
  val y:Int  //抽象字段,没有赋初值
  def f() = println("T:"+y)
}
class A extends T{
  val y=100  //实现抽象字段
}
def main(args:Array[String]): Unit ={
  val a=new A()
  println(a.x+" "+a.y)
  a.f()
}

----------------------------------

** scala支持对象混入多个特质,当调用同名方法时,最右边特质内的方法会被首先调用
** super指的是其左边的特质,只有当左边没有特质时,才会指向其父特质
原创粉丝点击