Scala基础(一)

Scala是一个门多范式的编程语言,设计初衷是集成面向对象编程和函数式编程的各种特性。

0.Scala的起源

Scala是一门多范式的编程语言,设计初衷是要集成面向对象编程和函数式编程(functional programming)的各种特性。洛桑联邦理工学院Martin Odersky于2001年基于[Funnel]的工作开始设计Scala。

什么是函数式编程?:函数是第一等公民,指的是函数与其他数据类型一样,处于平等地位,可以复制给其他变量,也可以作为参数传入另一个函数,或者作为别的函数的返回值。

1

1.Scala简介

Scala是一门支持面向对象编程和函数式编程的混合语言。它支持函数式编程的概念,比如不可变数据结构,把函数视为一等公民。在面向对象方面,它也支持类、对象、特质、封装、继承、多态和其他面向对象的概念。

Scala是一门静态类型的语言,通过编译时检查,保证代码的安全性和一致性。Scala应用程序是由Scala编译器编译的。Scala是类型安全的、Scala在编译期间会强制检查类型安全性。这有助于减少应用程序中的bug。

最后,Scala是一门基于JVM的语言。Scala编译器会将Scala应用程序编译成Java字节码,Java字节码运行在JVM上。从字节码的层面上看,Scala应用程序和Java应用程序没有区别。

2.基础类型

Scala与Java具有相同的数据类型,具有相同的内存占用和精度。以下是提供Scala中可用的所有数据类型的详细信息表格。

image.png

需要注意的是,Scala并没有基本类型。Scala的每一个基础类型都是一个类。当把一个Scala应用程序编译成Java字节码的时候,编译器会自动把Scala基础类型转变成为Java基本类型,这样有助于提高应用程序的性能。

3.变量

Scala有两种类型的变量:可变和不可变。不过,尽量不要使用可变变量。

可变变量使用关键字var声明,不可变量使用关键字val声明(常量)。

1
2
val y: Int = 10;
val y = 10

在Scala编译器能自动推导出类型的情况下,开发者不需要为它声明类型。使用Scala编程会使得代码更加简短精炼。

image.png

res0解释器自动创建的变量名称,用来指代表表达式的计算机结果。它是Int类型,值为2。

4.访问控制修饰符

Scala访问修饰符基本和Java的一样,分别有:privateprotectedpublic。作用类似与Java中一样。

5.函数

Scala把函数当成一等公民。函数可以当成变量使用。它可以作为输入传递给其他函数。它也可以定义成匿名函数字面量,就想字符串字面量一样。它可以作为变量的值。它也可以在其他函数的函数体内定义。它还可以作为其他函数的返回值返回。

Scala中用关键字def来定义函数。函数定义以函数名开头,紧跟着是以逗号作为分隔符的输入参数列表,每个参数后面跟着它们各自的类型,参数列表放在一对圆括号中。在右括号后面的一个冒号、函数返回值返回值类型、等号和函数体。

1
2
3
4
5
6
7
8
9
10
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.方法

方法是指类的成员函数。它的定义和使用方法和函数类似,唯一的区别就是它可以访问类里面的所有成员。

局部函数

在其他函数中或在方法中定义的函数称为局部函数。它仅可使用输入参数和包含它的函数内的变量。它只在含其定义的函数内可见。

高阶方法

把函数作为输入参数的方法被称为高阶方法。 类似的,高阶函数指的是把函数作为参数的函数。高阶方法和高阶函数有助于减少重复代码,从而使得代码更简洁。

下面是一个高阶函数的例子:

1
2
3
4
5
6
7
8
9
10
11
12
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

image.png

Scala中的符号=>可以看做是创建函数实例的语法。f:(Int) =>Long表示函数f的输入参数类型为Int,返回值类型是Long。另外,() => T表示函数输入参数为空,而A => Unit则表示函数没有返回值。

7.函数字面量(匿名函数)

函数字面量是指源代码中的匿名函数。在应用程序中,可以向字符字面量一样使用它。它可以作为高阶方法或高阶函数的参数,也可以复制给变量。

函数字面量的定义有处于圆括号中的输入函数列表、右箭头和函数体构成。包裹函数体的大括号是可选的。下面是一个函数字面量的例子。

1
2
3
(x:Int) =>{
x+100
}

如果函数体只有一条语句构成,那么大括号是可以省略的。上面定义的函数字面量的简化版如下所示。

1
(x:Int) => x+100

之前定义的高阶函数encode可以被当成函数字面量使用,如下所示。

1
val code = encode(10,(x:Int) => x +100)

8.闭包(Closure)

在函数对象的函数体中,只能使用参数和函数字面量中定义的局部变量。然而,Scala中的函数字面量却可以使用其所处作用域中的变量。闭包就是这种可以使用了非参数非局部变量的函数字面量。有时候人们把闭包和函数字面量当成同一术语,但是从技术上说,它们是不一样的。下面就是一个闭包的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
}
}

image.png

在上面的代码中,局部函数encode的第二个参数是个函数。这个函数字面量使用了两个变量n和seed。n是函数的参数,而seed却不是。在这个作为函数encode参数的函数字面量中,seed是从其所处的作用域获得的,并用在函数体中。

image.png

学习JavaScript闭包:闭包可以用在许多地方,它的最大用处有两个:

  • 1、可以读取函数内部的变量;
  • 2、让变量的值始终保持在内存中。

9.IDEA中学习Scala

####1.Scala中Object、Class、Trait的区别

image.png

具体区别如下:

image.png

参考资料

https://alvinalexander.com/scala/seq-class-methods-examples-syntax

https://docs.scala-lang.org/tour/tour-of-scala.html

文章目录
  1. 1. 0.Scala的起源
  2. 2. 1.Scala简介
  3. 3. 2.基础类型
  4. 4. 3.变量
  5. 5. 4.访问控制修饰符
  6. 6. 5.函数
  7. 7. 6.方法
    1. 7.1. 局部函数
    2. 7.2. 高阶方法
  8. 8. 7.函数字面量(匿名函数)
  9. 9. 8.闭包(Closure)
  10. 10. 9.IDEA中学习Scala
  11. 11. 参考资料