温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

一小时体验Scala

发布时间:2020-03-31 19:50:47 来源:网络 阅读:387 作者:bigstone2012 栏目:开发技术

浏览了一遍官方的介绍性文档,整理此文以飨大家。接下来,我们将要介绍Scala的基本使用,只是介绍其基本使用。

该教程可以做为你如厕时打发时间来用,因为这篇文章足够短。大篇幅的文章会挫败人的学习热情,好的文章读起来就像拉大便一样,能一口气很流畅地搞完,才会让人爽。所以,这必然又是一篇“入厕文章”,还是那句话,我希望本文能够让大家利用上下班,上厕所大便的时间学习一个技术。呵呵。

相信你现在已经在厕所里脱掉裤子露出屁股已经准备好大便了,那就让我们畅快地排泄吧……

[toc]

Scala介绍

Scala是一个现代的多范式编程语言。

Scala的特点:

  • 简洁

  • 优雅

  • 类型安全

  • 面向对象及函数式编程语言

Scala是一款纯面向对象的编程语言,也就意味着任何值都是对象。

Scala同时也是一款函数式编程语言,那也就意味着任何一个函数都是一个值。Scala支持匿名函数及高阶函数,允许函数嵌套。

Scala安装

Mac系统安装

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安装完毕。

Gnu/Linux安装

安装过程略。设置环境变量即可使用。


# /etc/profile

export JAVA_HOME=/usr/local/jdk

export SCALA_HOME=/usr/local/share/scala

export PATH=$PATH:$JAVA_HOME/bin:$SCALA_HOME/bin

第一个Scala程序

一般情况下,编程语言都会从一个“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

条件控制

绝大部分的编程语言在条件控制这一块基本一致,如果有过一门编程经验的话,条件控制这块完全不是问题。

while

[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

foreach

[lavenliu@mybox scala]$ cat foreach.scala 
args.foreach((arg) => println(arg))

执行:

$ scala foreach.scala Scala is Fun
Scala
is
Fun

for

$ 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

=&gt;的左边是参数列表,右边是函数体,很有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!

Case Classes

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

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

Traits

通过查字典才知道这个单词的有:特质、性状之意。根据其意思我们就可以推断,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 Method

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")
  }
}

行文至此,就先结束吧,想必你也拉完该提上裤子该去工作了。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI