scala学习笔记

Scala简介

Scala是一门现代的多范式编程语言,平滑地集成了面向对象和函数式语言的特性,旨在以简练、优雅的方式来表达常用编程模式。Scala的设计吸收借鉴了许多种编程语言的思想,只有很少量特点是Scala自己独有的。Scala语言的名称来自于“可伸展的语言”,从写个小脚本到建立个大系统的编程任务均可胜任。Scala运行于Java平台(JVM,Java 虚拟机)上,并兼容现有的Java程序,Scala代码可以调用Java方法,访问Java字段,继承Java类和实现Java接口。在面向对象方面,Scala是一门非常纯粹的面向对象编程语言,也就是说,在Scala中,每个值都是对象,每个操作都是方法调用。

Spark的设计目的之一就是使程序编写更快更容易,这也是Spark选择Scala的原因所在。总体而言,Scala具有以下突出的优点:
 Scala具备强大的并发性,支持函数式编程,可以更好地支持分布式系统;
 Scala语法简洁,能提供优雅的API;
 Scala兼容Java,运行速度快,且能融合到Hadoop生态圈中。

实际上,AMP实验室的大部分核心产品都是使用Scala开发的。Scala近年来也吸引了不少开发者的眼球,例如,知名社交网站Twitter已将代码从Ruby转到了Scala。
Scala是Spark的主要编程语言,但Spark还支持Java、Python、R作为编程语言,因此,若仅仅是编写Spark程序,并非一定要用Scala。Scala的优势是提供了REPL(Read-Eval-Print Loop,交互式解释器),因此,在Spark Shell中可进行交互式编程(即表达式计算完成就会输出结果,而不必等到整个程序运行完毕,因此可即时查看中间结果,并对程序进行修改),这样可以在很大程度上提升开发效率。现在的计算机都是多核CPU,想充分利用其多核处理,需要写可并行计算的代码。而函数式编程在并行操作性有着天生的优势,函数式编程没有可变变量,就不会有内存共享的问题。

 第一个Scala程序:Hello World

 Scala融合了面向对象编程思想,所以,这里我们采用一个包含了main()方法的大家比较熟悉的JVM应用程序,这里以Hello World程序为例进行说明。
请登录Linux系统,打开命令行终端(可以使用Ctr+Alt+T组合键来打开终端)。现在请在Scala安装目录/usr/local/scala下面新建一个mycode文件夹,用于存放自己的练习代码文件。

使用下面命令到达mycode目录,并新建一个test.scala文件:

cd /usr/local/scala
mkdir mycode

在test.scala文件中输入以下代码:

object HelloWorld {
    def main(args: Array[String]){
        println("Hello, World!")
    }
}

关于上面代码,需要重点说明两点:
(1)在上面代码中,定义了程序的入口main()方法。可以看出,关于main()方法的定义,Java和Scala是不同的,在Java中是用静态方法(public static void main(String[] args)),而Scala中则必须使用对象方法,本例中,也就是HelloWorld对象中的main()方法。
(2)对象的命名HelloWorld可以不用和文件名称一致,这里对象名称是HelloWorld,而文件名称却是test.scala。这点和Java是不同的,按照Java的命名要求,这里的文件名称就必须起名为HelloWorld.scala,但是,在Scala中是没有这个一致性要求的。
(3)Scala是大小写敏感的,所以,不要输入错误,比如把小写开头的object输成大写开头的Object。文件名Test.scala和test.scala也是两个不同的文件。

下面我们用scalac命令编译test.scala代码文件,并用scala命令执行,如下:

scalac test.scala //编译的时候使用的是Scala文件名称
scala -classpath . HelloWorld  //执行的时候使用的是HelloWorld对象名称

上述命令执行后,会在屏幕上打印出“Hello, World!”。

 Scala:声明值和变量

 Scala有两种类型的变量,一种是val,是不可变的,在声明时就必须被初始化,而且初始化以后就不能再赋值;另一种是var,是可变的,声明的时候需要进行初始化,初始化以后还可以再次对其赋值。

val变量

scala> val myStr = "Hello World!"
myStr: String = Hello World!

上面第1行代码是我们输入的代码,敲入回车后,Scala解释器会解析我们输入的代码,然后返回执行结果,第2行就是Scala解释器执行后返回的结果,从中我们可以看到,myStr变量的类型是String类型,变量的值是Hello World! 这里需要注意的是,尽管我们在第1行代码的声明中,没有给出myStr是String类型,但是,Scala具有“类型推断”能力,可以自动推断出变量的类型。

当然,我们也可以显式声明变量的类型:

scala> val myStr2 : String = "Hello World!"
myStr2: String = Hello World!

需要说明的是,上面的String类型全称是java.lang.String,也就是说,Scala的字符串是由Java的String类来实现的,因此,我们也可以使用java.lang.String来声明,具体如下:

scala> val myStr3 : java.lang.String = "Hello World!"
myStr3: String = Hello World!

但是,为什么可以不用java.lang.String,而只需要使用String就可以声明变量呢?这是因为,在每个应用程序中,Scala都会自动添加一些引用,这样,就相当于在每个程序源文件的顶端都增加了一行下面的代码:

import java.lang._ //java.lang包里面所有的东西

上面已经声明了一个String类型的不可变的变量,下面我们可以使用该变量,比如要打印出来:

scala> println(myStr)
Hello World!

上面的第1行代码是我们在scala命令提示符后面输入的代码,第2行是执行结果。

因为myStr是val变量,因此,一旦初始化以后,就不能再次赋值,所以,下面我们执行的再次赋值操作会报错:

scala> myStr = "Hello Scala!"
:27: error: reassignment to val
myStr = "Hello Scala!"
^

var变量

如果一些变量,需要在初始化以后还要不断修改它的值(比如商品价格),则需要声明为var变量。
下面我们把myPrice声明为var变量,并且在声明的时候需要进行初始化:

scala> var myPrice : Double = 9.9
myPrice: Double = 9.9

然后,我们可以再次对myPrice进行赋值:

scala> myPrice = 10.6
myPrice: Double = 10.6

如何在Scala解释器中输入多行代码

在Scala解释器中,当在命令提示符后面输入一个表达式并且按回车以后,代码就会被执行并显示出结果,比如下面我们输入一行表达式并回车:

scala> 2*9+4
res1: Int = 22
scala

这是输入单行代码的情形,但是,有时候,我们需要在命令提示符后面输入多行代码,这该如何实现呢?怎么才能让Scala解释器意识到你要输入多行代码呢?
在Java中,每个语句都是以英文的分号结束,但是,在Scala中,可以不用分号。当然,如果你想把多条语句全部写在一行上面,这时还是需要使用分号来隔开各个语句的。
通常而言,只要Scala解释器推断出你的代码还没有结束,应该延续到下一行,解释器就会在下一行显示一个竖线“|”,你可以继续输入剩余的代码,比如,我们要输入表达式val myStr4 = “Hello World!”,我们只在命令提示符后面输入“val myStr4 = ”然后就回车,显然,这个表达式还没有结束,所以,解释器会在下一行显示一个竖线“|”,你可以在第2行继续输入”Hello World!”然后回车,解释器就会得到执行结果,具体如下:

scala> val myStr4 =
| "Hello World!"
myStr4: String = Hello World!

此外,如果我们在命令提示符后面输入“val myStr5 = ”然后就回车,解释器会在下一行显示一个竖线“|”,这时如果我们发现变量名称错误,想放弃本次输入,就可以在“|”后面连续敲入两个回车,结束本次输入,具体如下:

scala> val myStr5 =
|
|
You typed two blank lines. Starting a new command.
scala>

 

 Scala入门:类

简单的类

最简单的类的定义形式是:

class Counter{
     //这里定义类的字段和方法
}

然后,就可以使用new关键字来生成对象:

new Counter //或者new Counter()

给类增加字段和方法

下面我们给这个类增加字段和方法:

class Counter {
    private var value = 0
    def increment(): Unit = { value += 1}
    def current(): Int = {value}
}

在上面定义中,我们把value字段设置为private,这样它就成为私有字段,外界无法访问,只有在类内部可以访问该字段。如果字段前面什么修饰符都没有,就默认是public,外部可以访问该字段。对于类而言,我们并不需要声明为public,Scala文件中包含的多个类之间,都是彼此可见的。

对于方法的定义,是通过def实现的。上面的代码“def increment(): Unit = { value += 1}”中,increment()是方法,没有参数,冒号后面的Unit是表示返回值的类型,在Scala中不返回任何值,那么就用Unit表示,相当于Java中的void类型。方法的返回值,不需要靠return语句,方法里面的最后一个表达式的值就是方法的返回值,比如,上面current()方法里面只有一条语句“value”,那么,value的值就是该方法的返回值。

因为increment()方法只是对value的值进行了增加1的操作,并没有返回任何值,所以,返回值类型是Unit。Unit后面的等号和大括号后面,包含了该方法要执行的具体操作语句。如果大括号里面只有一行语句,那么也可以直接去掉大括号,写成下面的形式:

class Counter {
    private var value = 0
    def increment(): Unit = value += 1 //去掉了大括号
    def current(): Int = {value}  //作为对比,这里依然保留大括号
}

或者,还可以去掉返回值类型和等号,只保留大括号,如下:

class Counter {
    private var value = 0
    def increment() {value += 1} //去掉了返回值类型和等号,只保留大括号
    def current(): Int = {value} //作为对比,这里依然保留原来形式
}

创建对象

下面我们新建对象,并调用其中的方法:

val myCounter = new Counter
myCounter.increment() //或者也可以不用圆括号,写成myCounter.increment
println(myCounter.current)

 

你可能感兴趣的:(scala学习笔记)