Essential Scala: Expressions, Types, and Values

简介

在这一章中,我们看看Scala中的基本构建块:表达式/类型/值.理解这些概念需要建立一个”Scala工作原理”的心智模型.

第一个程序

Compile-time and Run-time

编译的过程是检查程序意义的过程:

1. 必须句法正确
2. 类型检查

Expressions, Types, and Values

Expressions:表达式是一个程序文本的一部分,是Scala程序的主要组件.我们还将看到其他组件:定义或声明.表达式存在于编译时.表达式的定义特征是它的计算结果为一个值.

Values:值是存储在计算机内存的信息,存在于运行时.Scala中所有的值都是对象(object).

Types:类型是对程序中我们如何操作对象的限制.比如String可以调用toUpperCase方法,然而Int不行.在编译时进行检查,

重要的一点是,表达式拥有类型但是值没有,在不知道程序是如何创建的一个值时,我们并不能检查计算机内存中的一段值的类型,比如Scala中的整数和浮点值都是由32位内存表示.

Objects

一个对象是一组数据和对数据的操作.比如2是一个对象,数据是整数2,操作是一些类似=-等等.这些操作被称为method,而数据作为field.

方法调用

我们通过方法调用来影响对象,同时有些方法会接收一些参数来控制方法的执行.

Operators

因为Scala中的所有值都是对象,我们可以在一些原始类型上比如Int或Boolean上调用方法.与Java的差别就是Java中这些值并非对象.
作为对象,这些类似 + 或 - 的的操作同样也属于method.

Literal Objects

Numbers,Booleans,Chracters,Strings

Null: null在Java代码中经常用到,但是在Scala被认为是不好的代码实践. null值不能被编译器检查,而容易才运行时抛出NullPointerExceptions异常.

Unit: 写作 (), 是java中void的scala实现.

Object Literals

object Test {}

使用声明创建一个空对象.声明不同于表达式,表达式是进行求值,而声明是将一个值绑定到一个变量名.

Methods

object Test2 {
  def name: String = "Probably the best object ever"
}

声明一个方法.

方法声明语法:

def name(parameter: type, ...): resultType = bodyExpression

或:

def name: resultType = bodyExpression
  1. name是方法名
  2. 可选的parameters是传递给方法的参数名
  3. type是方法参数的类型
  4. resultType是方法返回结果的类型
  5. bodyExpression是该方法的求值过程表达式

Fields

一个Object同样可以包含其他对象,称为字段.

字段声明语法:

val name: type = valueExpression

或:

var name: type = valueExpression
  1. name是字段名
  2. 可选的type用于声明字段的类型
  3. valueExpression是求值表达式,将值绑定到字段名

val类型的值为immutable,不可修改,var是mutable,可以进行修改.尽量用val而不是var,避免可变性.

Methods versus fields

方法与字段的区别: 字段是讲一个值绑定到变量名,方法是将一个产生值得”计算”绑定到变量名.

object Test7 {
    val simpleField = {
        println("Evaluating simpleField")
        42
    }
    def noParameterMethod = {
        println("Evaluating noParameterMethod")
        42
    } 
}

运行:

Test7
// Evaluating simpleField
// res: Test7.type = Test7$@b22e8c9

当Object第一次被加载的时候,Scala会通过字段的定义对字段进行求值,并且只进行一次计算后存储到Object,后续再次进行调用时不会再次进行求值:

Test7.simpleField // res: Int = 42
Test7.simpleField // res: Int = 42

多次调用,仅返回第一次求得的值而不会再打印求值过程中出现的”Evaluating simpleField”.

但是method中的语句会在我们每次调用时都进行求值:

Test7.noParameterMethod
// Evaluating noParameterMethod 
// res: Int = 42
Test7.noParameterMethod
// Evaluating noParameterMethod 
// res: Int = 42

Writing Methods

  1. 定义输入和输出(类型)
  2. 准备测试用例
  3. 编写声明语句
  4. 编译运行进行检查
  5. 编写主体
  6. 再次编译运行检查

条件语句

if(1 < 2) "Yes" else "No"
// res: String = Yes

if(1 < 2) println("Yes") else println("No")
// Yes

条件语句声明格式:

if (condition) 
  trueExpression
else
  falseExpression
  1. condition是一个Boolean类型的表达式
  2. 如果condition为True,计算trueExpression表达式
  3. 如果condition为False,计算falseExpression表达式

Blocks

Block把多个计算表达式组合在一起.由多个表达式构成,由分号或换行分割并由大括号包围.

块表达式声明语法:

{
   declarationOrExpression ...
   expression
}
  1. 可选的声明或表达式
  2. 表达式,并且该表达式的类型与块类型一致