Scala笔记(5)——apply method

本文选自Deeper Look at the Apply Method in Scala

In Scala, there is a language feature generally referred to as “The Apply Method” that has the following rules:

Any object that has an apply method can be called with the .apply omitted.
Functions are no more than objects.

Let’s take a look at an example. Given the following abbreviated definition of class Array, and an instance a,

class Array{
def apply(index:Int) = { …some code to get from the array… }
}

val a = new Array(whatever)

Then the following calls are essentially equivalent:

a.apply(7)
a(7)

Scala语言的特性

Scala语言有以下几个特性:

(1)Scala代码运行在JVM上,因此可以利用Java语言的丰富资源。
(2)Scala语言是一门“纯面向对象的编程语言(pure object-oriented programming(OOP) language)”:每个变量都是对象,每个运算符都是方法;
(3)Scala语言也是一门函数式编程语言(functional programming(FP) language),因此可以把函数赋给变量。

Scala笔记(2)——val和var

Scala中,用val声明一个变量是不可改变的(immutable,read-only),而用var声明一个变量是可改变的(immutable,read-write)。同Java类似,Scala中许多变量实质上对分配在堆(heap)上的对象(object)的引用(reference),所以可变或不可变指的是引用可不可以指向不同的对象,而并非指引用的对象本身是否可以改变。看下面这个例子:

scala> val array: Array[String] = new Array(5)
array: Array[String] = Array(null, null, null, null, null)

scala> array[0] = "Hello"
<console>:1: error: identifier expected but integer literal found.
       array[0] = "Hello"
             ^

scala> array = new Array(2)
<console>:8: error: reassignment to val
       array = new Array(2)
             ^

array是一个val类型变量,array所指向数组的第一个元素可以改变(array[0] = "Hello"),但是array不能指向一个新的数组(array = new Array(2))。

Scala笔记(1)——一个入门的Scala程序

这是一个简单的入门Scala程序(iterate.scala):

object Iterate {
  def main (args: Array[String]) {
    args.foreach(s => println(s))
  }
}

在程序中,Iterate被定义成objectScalaobjectsingleton,也就是运行时只能产生一个Iterate实例。

main方法只能定义在object中,传入到main方法中的命令行参数是一个字符串数组:args: Array[String]main方法可以看成是Java类的static main方法,即Iterate程序的入口函数。

s => println(s)是一个functional literal,做的仅仅是打印s而已。

执行这个程序:

[root@Fedora scala]# scala iterate.scala  1 2
1
2

可以看出打印了命令行参数。

如何运行scala脚本

搭建Scala开发环境一文中可以看到不加任何参数直接运行scala命令时,会启动REPL(Read,Eval,Print,Loop)环境,然后就可以在这个环境里交互地执行Scala代码。本文介绍如何运行Scala脚本(script)。

首先创建一个简单的Scala脚本(hello.scala):

print("Hello world!\n")

a)直接运行scala hello.scala

[root@Fedora scala]# scala hello.scala
Hello world!

b)在REPL环境用load命令运行hello.scala

[root@Fedora scala]# scala
Welcome to Scala version 2.10.4 (OpenJDK 64-Bit Server VM, Java 1.8.0_45).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :load hello.scala
Loading hello.scala...
Hello world!

c)如果想把脚本编译成JVM byte code (一组*.class文件),可以使用scalac程序(命令行选项是-Xscript <object><object>是“main class”的名字,也即Java程序的入口):

[root@Fedora scala]# scalac -Xscript hello hello.scala
[root@Fedora scala]# ls
hello$$anon$1.class  hello.class  hello$.class  hello.scala
[root@Fedora scala]# scala hello
Hello world!

也可以用scalap这个逆向分析工具分析一下hello.class

[root@Fedora scala]# scalap -cp . hello
object hello extends scala.AnyRef {
  def this() = { /* compiled code */ }
  def main(argv : scala.Array[scala.Predef.String]) : scala.Unit = { /* compiled code */ }
}

Scala的“=>”符号简介

Scala中的=>符号可以看做是创建函数实例的语法糖。例如:A => TA,B => T表示一个函数的输入参数类型是“A”,“A,B”,返回值类型是T。请看下面这个实例:

scala> val f: Int => String = myInt => "The value of myInt is: " + myInt.toString()
f: Int => String = <function1>

scala> println(f(3))
The value of myInt is: 3

上面例子定义函数f:输入参数是整数类型,返回值是字符串。

另外,() => T表示函数输入参数为空,而A => Unit则表示函数没有返回值。