「这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战」。
一、函数
1、函数柯里化 & 闭包
闭包:函数式编程的标配
-
说明
闭包:如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包。
函数柯里化:把一个参数列表的多个参数,变成多个参数列表。
-
案例实操
-
闭包
def f1() = { var a: Int = 10 def f2(b: Int) = { a + b } f2 _ } // 在调用时,f1 函数执行完毕后,局部变量 a 应该随着栈空间释放掉 val f = f1() // 但是在此处,变量 a 其实并没有释放,而是包含在了 f2 函数的内部,形成了闭合的效果 println(f(3)) println(f1()(3)) -
函数柯里化
// 函数柯里化,其实就是将复杂的参数逻辑变得简单化,函数柯里化一定存在闭包 def f3()(b: Int) = { 1 + b } println(f3()(3))
-
2、递归
-
说明
一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用
-
案例实操
def main(args: Array[String]): Unit = {
// 阶乘
// 递归算法
// 1) 方法调用自身
// 2) 方法必须要有跳出的逻辑
// 3) 方法调用自身时,传递的参数应该有规律
// 4) scala 中的递归必须声明函数返回值类型
println(test(5))
}
def test(i : Int) : Int = {
if (i == 1) {
1
} else {
i * test(I - 1)
}
}
3、控制抽象
-
值调用
把计算后的值传递过去
def main(args: Array[String]): Unit = { def f = () => { println("f...") 10 } foo(f()) } def foo(a: Int): Unit = { println(a) } -
名调用
传名参数,传递的不再是具体的值,而是代码块
def f2(a: =>Int): Unit = { println("a: " + a) println("a: " + a) } f2(23) f2(f1()) f2({ println("这是一个代码块") 29 })
4、惰性加载
-
说明
当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。
-
案例实操
def main(args: Array[String]): Unit = { lazy val res = sum(10, 30) println("----------------") println("res=" + res) } def sum(n1: Int, n2: Int): Int = { println("sum 被执行。。。") return n1 + n2 }注意:lazy 不能修饰 var 类型的变量
二、面向对象
Scala 的面向对象思想和 Java 的面向对象思想和概念是一致的。
Scala 中语法和 Java 不同,补充了更多的功能。
1、Scala 包
-
基本语法
package 包名
-
Scala 包的三大作用(和 Java 一样)
区分相同名字的类
当类很多时,可以很好的管理类
控制访问范围
1.1、包的命名
-
命名规则
只能包含数字、字母、下划线、小圆点.,但不能用数字开头,也不要使用关键字。
-
案例实操
demo.class.exec1 //错误,因为 class 关键字 demo.12a //错误,数字开头 -
命名规范
一般是小写字母+小圆点
com.公司名.项目名.业务模块名
-
案例实操
com.moe.oa.model com.moe.oa.controller com.sohu.bank.order
1.2、包说明(包语句)
-
说明
Scala 有两种包的管理风格,一种方式和 Java 的包管理风格相同,每个源文件一个包(包名和源文件所在路径不要求必须一致),包名用“.”进行分隔以表示包的层级关系,如com.moe.scala。另一种风格,通过嵌套的风格表示层级关系,如下:
package com{ package moe{ package scala{ } } }第二种风格有以下特点:
一个源文件中可以声明多个 package
子包中的类可以直接访问父包中的内容,而无需导包
-
案例实操
package com { import com.moe.Inner //父包访问子包需要导包 object Outer { val out: String = "out" def main(args: Array[String]): Unit = { println(Inner.in) } } package moe { object Inner { val in: String = "in" def main(args: Array[String]): Unit = { println(Outer.out) //子包访问父包无需导包 } } } } package other { }
1.3、包对象
在 Scala 中可以为每个包定义一个同名的包对象,定义在包对象中的成员,作为其对应包下所有 class 和 object 的共享变量,可以被直接访问。
-
定义
package object com{ val shareValue="share" def shareMethod()={} } -
说明
- 若使用 Java 的包管理风格,则包对象一般定义在其对应包下的 package.scala文件中,包对象名与包名保持一致。
- 如采用嵌套方式管理包,则包对象可与包定义在同一文件中,但是要保证包对象与包声明在同一作用域中。
1.4、导包说明
- 和 Java 一样,可以在顶部使用 import 导入,在这个文件中的所有类都可以使用。
- 局部导入:什么时候使用,什么时候导入。在其作用范围内都可以使用
- 通配符导入:import java.util._
- 给类起名:import java.util.{ArrayList=>JL}
- 导入相同包的多个类:import java.util.{HashSet, ArrayList}
- 屏蔽类:import java.util.{ArrayList =>,}
- 导入包的绝对路径:new root.java.util.HashMap
2、类和对象
类:可以看成一个模板
对象:表示具体的事物
2.1、定义类
-
回顾:Java 中的类
如果类是 public 的,则必须和文件名一致。
一般,一个.java 有一个 public 类
注意:Scala 中没有 public,一个.scala 中可以写多个类。
-
基本语法
[修饰符] class 类名 {
类体
}
说明
- Scala 语法中,类并不声明为 public,所有这些类都具有公有可见性(即默认就是public)
- 一个 Scala 源文件可以包含多个类
-
案例实操
package com.moe.chapter06 //(1)Scala 语法中,类并不声明为 public,所有这些类都具有公有可见性(即默认就是 public) class Person { } //(2)一个 Scala 源文件可以包含多个类 class Teacher{ }
2.2、属性
属性是类的一个组成部分