您的位置:首页 > 职场人生

Java程序员的Scala教程 - 1

2012-06-20 21:17 585 查看
首先说明一下,这篇文章基本来自scala官网,说是翻译吧,也没有原本的把每句话翻下来,有些地方自己也多提了两句。顺便提一下自己工作也主要和Java打交道,废话不说了,正文如下:

官网教程: http://docs.scala-lang.org/tutorials/scala-for-java-programmers.html

习惯英文的直接上面传送。

1Introduce

对scala语言和编译进行一个简单的介绍。

2A First Example

第一个程序还用标准的 Hello World 来做例子。

objectHelloWorld{
def main(args:Array[String]){
println("Hello, world!")
}
}


和Java程序比较类似,他包含了一个main方法来接收命令行参数;方法调用预定义的方法println。main方法没有返回值(procedure
method 过程方法),所以也不需要对这个方法声明返回类型。

对于java程序员,有以下几点要说明:

object

object声明了这是一个单例对象(singleton
object)。它同时声明了一个名为HelloWorld的类,和一个叫做HolloWorld的实例,这个实例在第一次调用的时候创建。

static

在scala里面没有static这个概念,无论是字段还是方法。所以上面的main方法没有static关键字。所有需要声明为static的东西,都在单例对象中声明,就是上面说的object。

public

例子中main函数也没有public关键字,因为在scala中所有没有指定范围的东西(方法、成员)都默认为public的。

2.1Compiling the example

用scalac这个scala的编译器来编译上面程序。和大部分的编译器一样,运行它需要一个文件名,也可以加上其他的选项,然后产生一个或多个对象文件。Scalac生成的对象文件是标准的Java
class文件。

比如编译上面的例子:

>
scalac
HelloWorld.scala

会在当前目录产生几个class文件,其中一个是HelloWorld.class,还包含一个可以直接被scala命令执行的class,如下节所示。

2.2Running the example

编译好,就可以用scala命令运行了,类似java命令:

>
scala
-
classpath
.
HelloWorld


>
Hello
,
world
!


3Interaction with Java

Scala可以很简单的和Java代码交互。Java.lang包中的所有类都会被scala默认导入,而其他的java类就需要自己明确的导入了。

看一个简单的实例:我们希望获取当前时间并用法国风格的格式来格式输出。因为java定义了强大的类库,比如Date、DateFormat,我们不需要再引入scala中这些等价的类:

import java.util.{Date, Locale}
import java.text.DateFormat
import java.text.DateFormat._

object FrenchDate {
def main(args: Array[String]) {
val now = new Date
val df = getDateInstance(LONG, Locale.FRANCE)
println(df format now)
}
}


scala的import和java的差不多,但是更强大。以下需要注意:

同一个包中的不同类可在同一行引入,用大括号包起来就行了

导入包中的全部类,用_来代替java中的*,因为*在scala中是一个有效的标识符(下面会介绍)

不仅能导入类,而且能导入类中的静态方法和静态字段(都是对象啦),程序中的
getDateInstance,
LONG

分析代码第一句,创建一个
Date
实例,val是不可变对象的声明(val、var以后会讲)。然后创建一个日期格式对象,getDateInstance
是之前import的静态方法。然后打印出来,打印时用到了sacal一个有意思的语法,

表达式:

df format
now

相当于:

df.format(now)

和java交互,不仅能使用它的类,还可以直接继承一个java类、实现某个java接口。

4Everything is an Object

Scala是纯面向对象的语言,everything
is an
object,包括数字、方法。和java不同,java有原始类型(int、boolean、short)和引用类型,并且不能像操作值一样操作方法。

4.1数字是对象

数字是对象,那么当然应该有方法了,其实常用的操作符就是啦:

1
+
2
*
3
/
x

根据上面提到的,等价于:

(1).+(((2).*(3))./(x))

也就是说在scala里,+,*,等都是有效的标识符。

第二种写法数字两遍的小括号是必须的,因为scala对标记使用了最长匹配规则,如下:

1.+(2)

会被解释为:

1.

+

2

三部分,因为点更接近1,而1.会背认为是1.0,那样就不是一个Int了,而是当作用一个Double来计算。

(1).+(2)

上面这样写才对。

4.2方法是对象

这可能让Java程序员感到更加惊奇,在scala中方法也是对象。可以把方法当作参数来传递,存储在一个变量里,作为返回值。这种操作函数的能力称为函数式编程。(函数式编程有很多探讨,可以google: functional
programming)

一个简单的例子来说明如何想操作值一样使用方法。考虑一个计数函数,没秒来执行一些操作。我们要如何包计数操作传递给这个计数函数呢?当然是作为一个函数了。这种简单的函数传递对很多程序员都不陌生,经常用在用户接口程序,来注册一个回调函数(当某些事件发生时触发)。

下面程序中,计数函数名为oncePerSecond,拥有一个回调函数作为参数,回调函数的类型写为()
=> Unit,这是对所有没有参数、没有返回值的函数的一种写法。

Scala中类型声明和java不一样,区别如下

Java: String name;

scala: val name: String

java: Integer getSumInteger();

scala: def getSumInteger: Integer

Unit类似与void。main函数调用计数函数,传递一个回调函数作为参数。这个程序会每个一秒println一次,一直到你电脑关机(如果不结束程序)。

object Timer {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}

def timeFlies() {
println("time flies like an arrow...")
}

def main(args: Array[String]) {
oncePerSecond(timeFlies)
}
}


4.3匿名函数
Anonymous functions

上面例子定义的timeFiles函数,只被用到了一次,定义出来有点浪费,在scala中完全可以用匿名函数代替。改写后如下:

object TimerAnonymous {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def main(args: Array[String]) {
oncePerSecond(() =>
println("time flies like an arrow..."))
}
}


匿名函数用=>来区分函数的参数列表和函数体。当然这个匿名函数的没有参数,也就是一个(),在=>的左边,右边就是函数体,只有一句话。

5Classes

scala中的class定义和java差不多,而且增加了类参数:

class
Complex(real: Double, imaginary: Double) {

def
re() = real

def
im() = imaginary

}

这个类包含了两个参数,两个方法。生成实例时必须要包含这两个参数:

new
Complex(1.5, 2.3)

注意上面两个方法都没有标明返回值,scala编译器会根据函数体自动推断(例子中为Double)。默认会在函数体的最后一句话前加上一个return,这点以后开单张讲解。

5.1无参方法
Methods without arguments

一个小问题:当调用方法时必须加上一个小括号(方法没有参数时):

object
ComplexNumbers {

def
main(args: Array[String]) {

val
c = new
Complex(1.2, 3.4)

println("imaginary
part: " + c.im())

}

}

在scala中,对于0参数的方法,无论定义或者调用都可以把小括号省略,如下:

class
Complex(real: Double, imaginary: Double) {

def
re = real

def
im = imaginary

}

5.2继承和重写
Inheritance and overriding

Scala中的任何类都集成自父类,如果没有声明父类(上面例子),会隐含集成scala.AnyRef类。

重写父类方法必许使用override关键字修饰:

class
Complex(real: Double, imaginary: Double) {

def
re = real

def
im = imaginary

overridedef
toString() =

""
+ re + (if
(im < 0) ""else"+")
+ im + "i"

}

今天到这里,明天明天继续。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: