Scala是一个门多范式的编程语言,设计初衷是集成面向对象编程和函数式编程的各种特性。
0.Scala的起源
Scala是一门多范式的编程语言,设计初衷是要集成面向对象编程和函数式编程(functional programming
)的各种特性。洛桑联邦理工学院的Martin Odersky
于2001年基于[Funnel]的工作开始设计Scala。
什么是函数式编程?:函数是第一等公民,指的是函数与其他数据类型一样,处于平等地位,可以复制给其他变量,也可以作为参数传入另一个函数,或者作为别的函数的返回值。
1.Scala简介
Scala是一门支持面向对象编程和函数式编程的混合语言。它支持函数式编程的概念,比如不可变数据结构,把函数视为一等公民。在面向对象方面,它也支持类、对象、特质、封装、继承、多态和其他面向对象的概念。
Scala是一门静态类型的语言,通过编译时检查,保证代码的安全性和一致性。Scala应用程序是由Scala编译器编译的。Scala是类型安全的、Scala在编译期间会强制检查类型安全性。这有助于减少应用程序中的bug。
最后,Scala是一门基于JVM的语言。Scala编译器会将Scala应用程序编译成Java字节码,Java字节码运行在JVM上。从字节码的层面上看,Scala应用程序和Java应用程序没有区别。
2.基础类型
Scala与Java具有相同的数据类型,具有相同的内存占用和精度。以下是提供Scala中可用的所有数据类型的详细信息表格。
需要注意的是,Scala并没有基本类型。Scala的每一个基础类型都是一个类。当把一个Scala应用程序编译成Java字节码的时候,编译器会自动把Scala基础类型转变成为Java基本类型,这样有助于提高应用程序的性能。
3.变量
Scala有两种类型的变量:可变和不可变。不过,尽量不要使用可变变量。
可变变量使用关键字var
声明,不可变量使用关键字val
声明(常量)。
val y: Int = 10;
val y = 10
在Scala编译器能自动推导出类型的情况下,开发者不需要为它声明类型。使用Scala编程会使得代码更加简短精炼。
res0
解释器自动创建的变量名称,用来指代表表达式的计算机结果。它是Int类型,值为2。
4.访问控制修饰符
Scala访问修饰符基本和Java的一样,分别有:private
、protected
、public
。作用类似与Java中一样。
5.函数
Scala把函数当成一等公民。函数可以当成变量使用。它可以作为输入传递给其他函数。它也可以定义成匿名函数字面量,就想字符串字面量一样。它可以作为变量的值。它也可以在其他函数的函数体内定义。它还可以作为其他函数的返回值返回。
Scala中用关键字def来定义函数。函数定义以函数名开头,紧跟着是以逗号作为分隔符的输入参数列表,每个参数后面跟着它们各自的类型,参数列表放在一对圆括号中。在右括号后面的一个冒号、函数返回值返回值类型、等号和函数体。
object Hello {
def max(x: Int, y: Int ):Int= {
if (x>y) x
else y
}
def main(args: Array[String]): Unit = {
val m =max(3,4)
print(m)
}
}
6.方法
方法是指类的成员函数。它的定义和使用方法和函数类似,唯一的区别就是它可以访问类里面的所有成员。
局部函数
在其他函数中或在方法中定义的函数称为局部函数。它仅可使用输入参数和包含它的函数内的变量。它只在含其定义的函数内可见。
高阶方法
把函数作为输入参数的方法被称为高阶方法。 类似的,高阶函数指的是把函数作为参数的函数。高阶方法和高阶函数有助于减少重复代码,从而使得代码更简洁。
下面是一个高阶函数的例子:
object Test {
//将函数f当做参数传入进去
def encode(n:Int,f:(Int) =>Long): Long ={
val x = n*10
f(x)
}
def main(args: Array[String]): Unit = {
//传入函数f的具体表达式
val res = encode(10,(x)=>2*x)
print(res)
}
}
encode
函数接受两个参数,返回一个Long
类型的值。第一个参数是Int
类型的,第二个参数是一个函数f
,它接受一个Int
类型的参数,返回一个Long
类型的值。encode
函数首先将第一个参数乘以10,然后将结果作为参数调用函数f
,函数f
的表达式是2*x
。
Scala中的符号
=>
可以看做是创建函数实例的语法。f:(Int) =>Long
表示函数f的输入参数类型为Int,返回值类型是Long。另外,() => T
表示函数输入参数为空,而A => Unit
则表示函数没有返回值。
7.函数字面量(匿名函数)
函数字面量是指源代码中的匿名函数。在应用程序中,可以向字符字面量一样使用它。它可以作为高阶方法或高阶函数的参数,也可以复制给变量。
函数字面量的定义有处于圆括号中的输入函数列表、右箭头和函数体构成。包裹函数体的大括号是可选的。下面是一个函数字面量的例子。
(x:Int) =>{
x+100
}
如果函数体只有一条语句构成,那么大括号是可以省略的。上面定义的函数字面量的简化版如下所示。
(x:Int) => x+100
之前定义的高阶函数encode可以被当成函数字面量使用,如下所示。
val code = encode(10,(x:Int) => x +100)
8.闭包(Closure)
在函数对象的函数体中,只能使用参数和函数字面量中定义的局部变量。然而,Scala中的函数字面量却可以使用其所处作用域中的变量。闭包就是这种可以使用了非参数非局部变量的函数字面量。有时候人们把闭包和函数字面量当成同一术语,但是从技术上说,它们是不一样的。下面就是一个闭包的例子。
object Test {
def main(args: Array[String]): Unit = {
val res = encodeWithSeed(2,5)
print(res)
}
def encodeWithSeed(num:Int,seed:Int):Long ={
//x值是从encode(num,(n:Int) => (n*seed))从获取的
def encode(x:Int,func:(Int)=>Int):Long={
val y = x+1000
//将y的结果作为func函数的参数
func(y)
}
//最后计算n*seed作为最后的result
val result = encode(num,(n:Int) => (n*seed))
result
}
}
在上面的代码中,局部函数encode
的第二个参数是个函数。这个函数字面量使用了两个变量n和seed
。n是函数的参数,而seed却不是。在这个作为函数encode
参数的函数字面量中,seed
是从其所处的作用域获得的,并用在函数体中。
学习JavaScript闭包:闭包可以用在许多地方,它的最大用处有两个:
- 1、可以读取函数内部的变量;
- 2、让变量的值始终保持在内存中。
9.IDEA中学习Scala
1.Scala中Object、Class、Trait的区别
具体区别如下:
参考资料
https://alvinalexander.com/scala/seq-class-methods-examples-syntax