您好,登录后才能下订单哦!
浏览了一遍官方的介绍性文档,整理此文以飨大家。接下来,我们将要介绍Scala的基本使用,只是介绍其基本使用。
该教程可以做为你如厕时打发时间来用,因为这篇文章足够短。大篇幅的文章会挫败人的学习热情,好的文章读起来就像拉大便一样,能一口气很流畅地搞完,才会让人爽。所以,这必然又是一篇“入厕文章”,还是那句话,我希望本文能够让大家利用上下班,上厕所大便的时间学习一个技术。呵呵。
相信你现在已经在厕所里脱掉裤子露出屁股已经准备好大便了,那就让我们畅快地排泄吧……
[toc]
Scala是一个现代的多范式编程语言。
Scala的特点:
简洁
优雅
类型安全
Scala是一款纯面向对象的编程语言,也就意味着任何值都是对象。
Scala同时也是一款函数式编程语言,那也就意味着任何一个函数都是一个值。Scala支持匿名函数及高阶函数,允许函数嵌套。
Mac下安装非常简单,从Scala官网下载二进制包,然后解压到某个路径下,设置环境变量就搞定了。比如把Scala安装到/usr/local/share/scala下,如下:
wget https://downloads.lightbend.com/scala/2.12.2/scala-2.12.2.tgz
tar -xf scala-2.12.2.tgz
mv scala-2.12.2 /usr/local/share/scala
设置环境变量:
export SCALA_HOME=/usr/local/share/scala
PATH="/Library/Frameworks/Python.framework/Versions/3.5/bin:${GOPATH}/bin:${SCALA_HOME}/bin:${PATH}"
export PATH
重新加载.bash_profile文件:
. ~/.bash_profile
验证scala是否可用:
LavenLius-MacPro:scala liuchuan$ scala
Welcome to Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_91).
Type in expressions for evaluation. Or try :help.
scala>
至此,Scala安装完毕。
安装过程略。设置环境变量即可使用。
# /etc/profile
export JAVA_HOME=/usr/local/jdk
export SCALA_HOME=/usr/local/share/scala
export PATH=$PATH:$JAVA_HOME/bin:$SCALA_HOME/bin
一般情况下,编程语言都会从一个“Hello,World!”程序着手,我们也从一个“Hello,World!”开始,看看Scala的程序是如何写的。在Scala的交互式环境及写成文件的形式都是可以的。
LavenLius-MacPro:scala liuchuan$ cat HelloWorld.scala
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, Scala!")
}
}
编译并运行。scalac
命令可以编译一个或多个Scala源文件并生成可以被任何标准的JVM虚拟机执行的Java字节码。Scala的编译器类似Java的编译器javac
。默认情况下,scalac
会在当前目录下生成class文件。我们可以使用-d
选项,指定class文件位置。
# 在当前目录生成class文件
LavenLius-MacPro:scala liuchuan$ scalac HelloWorld.scala
# 指定生成class文件的目录
LavenLius-MacPro:scala liuchuan$ scalac -d classes HelloWorld.scala
LavenLius-MacPro:scala liuchuan$ scala -classpath . HelloWorld
Hello, Scala!
# cp选项是classpath的别名
LavenLius-MacPro:scala liuchuan$ scala -cp . HelloWorld
Hello, Scala!
如果不编译文件,可以以脚本的形式来执行:
[lavenliu@mybox scala]$ scala HelloWorld.scala
Hello, Scala!
表达式就是可以被计算的语句,如:
1 + 1
我们可以使用println
来打印表达式的结果:
scala> println(1)
1
scala> println(1 + 1)
2
scala> println("Hello!")
Hello!
scala> println("Hello" + "world!")
Helloworld!
我们可以使用val
关键字给表达式命名,val
有点final
的意思,一旦赋值不能再次更改。很像ES6中的let
关键字。
scala> val x = 1 + 1
x: Int = 2
scala> println(x)
2
像上面的为表达式的结果命名,如x,我们称之为values
。给值重新赋值,将会发生编译错误,也就是说,values不能重新赋值。
scala> val x = 1 + 1
x: Int = 2
scala> x = 3
<console>:12: error: reassignment to val
x = 3
^
values的类型可以被自动推导出来,就像上面的x: Int = 2
一样,不过我们可以明确指定值的类型,就像下面这样:
scala> val x: Int = 1 + 1
x: Int = 2
注意到,类型Int
跟在值x
后面,并且值x
后面的:
不能省略。
与其他语言对比,类似JavaScript中的const
定义的常量。
变量跟值类似,只不过变量可以重新赋值。我们可以使用关键字var
定义变量,var
定义的变量是非final
的。
scala> var x = 1 + 1
x: Int = 2
scala> x = 3
x: Int = 3
scala> println(x * x)
9
同样,我们也可以在定义变量时指定其类型:
scala> var x: Int = 1 + 1
x: Int = 2
我们可以把一些语句组织在一个块中,使用{}
。我们称之为block
。语句块的结果就是最后一个表达式的结果(类似lisp语言中的let
函数)。
scala> println({
val x = 1 + 1
x + 1
})
3
# 上面的代码块返回值为3,是x+1的结果,x为2
绝大部分的编程语言在条件控制这一块基本一致,如果有过一门编程经验的话,条件控制这块完全不是问题。
[lavenliu@mybox scala]$ cat while01.scala
var i = 0
while (i < 10) {
println(i)
i += 1
}
执行:
[lavenliu@mybox scala]$ scala while01.scala
0
1
2
3
4
5
6
7
8
9
[lavenliu@mybox scala]$ cat foreach.scala
args.foreach((arg) => println(arg))
执行:
$ scala foreach.scala Scala is Fun
Scala
is
Fun
$ cat for.scala
for (arg <- args)
println(arg)
执行:
$ scala for.scala Scala is Fun
Scala
is
Fun
函数可以理解为带参数的表达式,既然是表达式就可以把它赋值给变量。既然可以当做变量来用,那么这门语言是支持函数式编程的,又支持高阶函数。
我们可以定义匿名函数,是不是很像某个语言的箭头函数?是不是也很像Java 8的lambda表达式?
scala> (x: Int) => x + 1
res20: Int => Int = $$Lambda$1245/1467853846@18ed9480
在=>
的左边是参数列表,右边是函数体,很有JavaScript的味道。
我们也可以定义命名函数:
scala> val addOne = (x: Int) => x + 1
addOne: Int => Int = $$Lambda$1246/1214357269@790ea58f
scala> addOne(3)
res21: Int = 4
函数可有多个参数,
scala> val add = (x: Int, y: Int) => x + y
add: (Int, Int) => Int = $$Lambda$1257/368310735@7b8d1537
scala> println(add(1, 2))
3
函数也可以没有参数,
scala> val getTheAnswer = () => 42
getTheAnswer: () => Int = $$Lambda$1259/608738578@28df2da8
scala> println(getTheAnswer())
42
方法看起来及其行为与函数很像,不过它们之间也有细微之处。方法的定义是使用def
关键字,def
后面跟方法名称、参数列表、返回类型及方法体。
scala> def add(x: Int, y: Int): Int = x + y
add: (x: Int, y: Int)Int
scala> println(add(2, 3))
5
注意,方法的返回值声明是在参数列表后面跟一个冒号及类型。方法的参数要指定参数的类型,因为编译器不推断参数的类型,返回值也是同样要指定类型。方法定义中的=
也需要注意,在函数式编程语言中,方法的定义是一个表达式并且可以赋值给一个变量。
方法可以接收多个参数列表。
scala> def addTheMultiply(x: Int, y: Int)(multipliter: Int): Int = (x+y)*multipliter
addTheMultiply: (x: Int, y: Int)(multipliter: Int)Int
scala> print
print printf println
scala> println(addTheMultiply(1, 2)(3))
9
来一个没有参数的方法:
scala> def name: String = System.getProperty("name")
name: String
scala> println("Hello, " + name + "!")
Hello, null!
方法虽然与函数有些不同,不过到目前为止,我们可以认为方法与函数长得很像,只是很像。
方法可以有多行表达式。
scala> def getSquareString(input: Double): String = {
val square = input * input
square.toString
}
getSquareString: (input: Double)String
scala> getSquareString(4.0)
res32: String = 16.0
方法体中的最后一个表达式就是方法的返回值。(Scala没有return
关键字,因为它很少用到。这种情况在Lisp、Ruby、Julia中也很常见。)如果方法体中只有一行表达式,那么可以省略方法体上的大括号。
还可以定义一个无参数及无返回值的方法,如下:
scala> def greet() = println("hello, world!")
greet(): Unit
如果一个方法返回Unit
类型,则表示该方法返回没有实际意义的值,类似其他语言中的void
返回类型。
我们可以使用class
关键字定义类,后面跟类的名称及构造参数。
scala> class Greeter(prefix: String, suffix: String) {
def greet(name: String): Unit =
println(prefix + name + suffix)
}
defined class Greeter
方法greet
的返回类型为Unit
,也就是说,该方法并不返回什么有意义的东东。Unit
其实跟C或Java中的void
类似。(A difference is that because every Scala expression must have some value, there is actually a singleton value of type Unit, written (). It carries no information.)
定义了一个类后,怎么使用呢?可以使用关键字new
来实例化。
scala> val greeter = new Greeter("Hello, ", "!")
greeter: Greeter = Greeter@202e6fd0
scala> greeter.greet
def greet(name: String): Unit
scala> greeter.greet("Scala developer")
Hello, Scala developer!
Scala有一种特殊的类叫做“case
”类。默认情况下,case
类是不可变的,只可以比较其值。我们可以使用case class
关键字定义case类。
scala> case class Point(x: Int, y: Int)
defined class Point
我们可以不使用new
关键字就可以实例化case类。
scala> val point = Point(1, 2)
point: Point = Point(1,2)
scala> val anotherPoint = Point(1, 2)
anotherPoint: Point = Point(1,2)
scala> val yetAnotherPoint = Point(2, 2)
yetAnotherPoint: Point = Point(2,2)
case类通过值进行比较。
scala> if (point == anotherPoint) {
println(point + " and " + anotherPoint + " are the same.")
} else {
println(point + " and " + anotherPoint + " are different.")
}
Point(1,2) and Point(1,2) are the same.
scala> if (point == yetAnotherPoint) {
println(point + " and " + yetAnotherPoint + " are the same.")
} else {
println(point + " and " + yetAnotherPoint + " are different.")
}
Point(1,2) and Point(2,2) are different.
case类暂时介绍到这里,后续会继续深入讲解。
Objects are single instances of their own definitions. You can think of them as singletons of their own classes.这句话可以简单理解为 Objects
是其自身的一个实例,相对于单例类。
我们可以使用关键字object
定义Objects。
scala> object IdFactory {
private var counter = 0
def create(): Int = {
counter += 1
counter
}
}
defined object IdFactory
我们通过引用其名字就可以访问:
scala> val newId: Int = IdFactory.create()
newId: Int = 1
scala> println(newId)
1
scala> val newerId: Int = IdFactory.create()
newerId: Int = 2 # 这里的值是2,而不是1,那就有点意思了
scala> println(newerId)
2
通过查字典才知道这个单词的有:特质、性状之意。根据其意思我们就可以推断,Scala中的Traits应该是接口相关的东东了。官方的解释是:"Traits are types containing certain fields and methods. Multiple traits can be combined."
You can define traits with trait
keyword.
scala> trait Greeter {
def greet(name: String): Unit
}
defined trait Greeter
Traits 可以有默认的实现。
scala> trait Greeter {
def greet(name: String): Unit =
println("Hello, " + name + "!")
}
defined trait Greeter
You can extend traits with the extends
keyword and override an implementation with the override
keyword. 这句话可以理解为Traits可以继承或扩展。
scala> trait Greeter {
def greet(name: String): Unit =
println("Hello, " + name + "!")
}
defined trait Greeter
scala> class DefaultGreeter extends Greeter
defined class DefaultGreeter
scala> class CustomizableGreeter(prefix: String, postfix: String) extends Greeter {
override def greet(name: String): Unit = {
println(prefix + name + postfix)
}
}
defined class CustomizableGreeter
scala> val greeter = new DefaultGreeter()
greeter: DefaultGreeter = DefaultGreeter@61bb1e4d
scala> greeter.greet("Scala developer")
Hello, Scala developer!
scala> val customGreeter = new CustomizableGreeter("How are you, ", "?")
customGreeter: CustomizableGreeter = CustomizableGreeter@5fb07347
scala> customGreeter.greet("Scala developer")
How are you, Scala developer?
上面的例子中,DefaultGreeter
只扩展了一个单个trait,不过它可以扩展多个traits。
main方法是程序的入口点。JVM需要一个名为main的主方法并且需要一个字符串数组作为参数。
使用一个object,我们可以定义main方法如下:
scala> object Main {
def main(args: Array[String]): Unit =
println("Hello, Scala developer!")
}
defined object Main
上述main
方法的返回值Unit
类似其它语言中的void
,不过可以省略不写。但是main
方法的参数是不能省略的,不一定非得叫args
,如果省略了,就会出现错误提示“java.lang.NoSuchMethodException: Main.main([Ljava.lang.String;)
”。上面的object还可以这样写:
object World {
def main(laven: Array[String]) {
println("World")
}
}
行文至此,就先结束吧,想必你也拉完该提上裤子该去工作了。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。