从技术上来讲,scala程序并不是一个解释器,你在命令行中输入的内容被快速地编译成字节码,然后这段字节码交给Java虚拟机执行。
变量声明:
val | val不能再继续赋值, | 鼓励使用该命令方式 |
var | 生命周期中可以被多次赋值 | 大多数程序并不需要那么多var变量 |
scala中变量或函数的类型总是写在变量或函数名称后面:
val greeting: String = "Hello"
仅当同一行代码中存在多条语句时才需要用分号隔开。
scala中的数组
如果数组的长度固定,使用Array,如果长度可能有变化则使用ArrayBuffer,通过ArrayBuffer.toArray方法返回Array;
如果需要遍历数组,数组和数组列表有一些语法上的不同,for循环的语法:
for (i <- 0 until a.length) println(i+”:”+a(i))
until是RichInt类的方法,返回所有小于(但不包括)上限的数字,可以使用 until(end, step)来限定跳跃的步数,进行定制化的遍历操作;还可以使用reverse方法来反转整个Range。
对于scala来说,以某种方式对它进行转换是非常简单的,这些转换动作不会修改原始数组,而是产生一个全新的数值,可以使用 for (elem <- a) yield 2 * elem 来返回一个类型与原始集合相同的新集合(并不会修改原始数组),当然也可以按照下面的方式,仅针对某几个过滤好的元素来操作:
for (elem <- a if elem % 2 == 0) yield 2 * elem
数组中也提供了一些比较常用的算法,
- sum: 可以调用sum操作来获取Array其值的总和;
- min:Array的最小值;
- max:Array中的最大值;
- sorted:将Array或ArrayBuffer排序并返回经过排序的Array/ArrayBuffer,不会修改原始版本;
- sortWith:提供函数用于排序;
- scala.util.Sorting.quickSort(数组)
- mkString: 连接数组中的字符串,可以定义连接符,起始和结束符号;
scala数组是用Java数组实现的,可以在Java与Scala之间来回传递,但是可以使用更加方便的方式,引入scala.collection.JavaConversions中的隐式转换方法,这样就可以在代码中直接使用Java的集合。
映射和元组
scala中可以使用下面的方式来创建映射:
val scores = Map("Alice"->10, "Bob"->3, "Cindy"->4)
->操作符可以用于创建对偶,对偶 “Alice”->10, 产出的值为(“Alice”, 10)。
在scala中,函数与映射之间的相似性尤为明显,将使用()表示法来查找某个键对应的值,scores(“Alice”);getOrElse(key, default)来获取某个值,当key不存在时使用default值代替。
如果想要更新映射中的值,可以对()的值进行赋值操作:scores(“Alice”)=20,或者通过+=操作来添加多个关系,-=来移除某个键和对应的值。
对于映射的迭代,可以用循环来进行遍历:
for ((k,v) <- 映射) 处理k和v
如果需要反转一个映射,交换键和值的位置,可以使用for yield操作来简单实现:
for ((k,v) <- 映射) yield (v,k)
如果需要实现与Java Map的互操作,可以通过增加import scala.collection.JavaConversions.mapAsScalaMap/mapAsJavaMap来实现。
映射是键值对偶的集合,对偶是元组tuple的最简单形态,它只有两个元素,而元组是可以包含多个元素的,Tuple[Int, Double, java.lang.String],访问元组的方式比较简单,只需要根据 variable._1 ._2这种方式来实现。
使用元组的原因之一就是把多个值绑在一起,使它们能够被一起处理,这通常用zip方法来完成:
val symbols = Array("<", "-", ">") val counts = Array(2, 10, 2) val pairs = symbols.zip(counts)
//生成的pairs就会存在一个 Tuple的集合 (“>”, 2), (“-“, 10), (“>”, 2)
类-class
scala中,类并不声明为public,方法默认是public的。scala源文件中可以包含多个类,所有这些类型都具有公有可见性。在调用无参方法时,可以写上圆括号,也可以不写。关于这点的最佳实践是,对于setter类型的方法使用括号,而getter类型的方法不用使用括号。
在编写Java类时,我们往往不喜欢使用公有字段,scala中对每个字段都提供getter/setter方法,假如字段名为age,则getter/setter方法名称分别叫做age和age_=。scala中对每个字段生成getter/setter方法听上去比较恐怖,但我们可以控制该过程:
- 如果字段是私有的,则getter/setter方法也是私有的;
- 如果字段是val,则只有getter方法被生成(该字段对应java的final属性);
- 如果不需要任何getter/setter,可以将字段声明为private[this];
在scala/Java中,方法可以访问该类的所有对象私有字段,但在scala中允许我们定义更加严格的访问限制,通过private[this]这个修饰符来实现,且该字段不会生成getter/setter方法。
scala提供生成的getter/setter方法针对Java的Bean规范时,可能并不是预期的,很多Java规范依赖getFoo/setFoo这种类型的命名规范。当在scala字段中标注@BeanProperty时,这样的方法就会自动生成了。
与Java一样,scala中也可以有任意多的构造器,不过scala中有着主构造器(primary constructor)的概念,除了主构造器之外,类还可以有任意多个辅助构造器。
辅助构造器的名称为this,每一个辅助构造器都必须以一个对先前已定义的其他辅助构造器或主构造器的调用开始。一个类如果没有显示地定义主构造器则自动拥有一个无参的主构造器。
在scala中每个类都会有主构造器,主构造器并不以this方法定义,而是与类定义交织在一起。
主构造器的参数直接放置在类名之后,主构造器的参数被编译成字段,其值被初始化成构造时传入的参数,主构造器会执行类定义中的所有语句:
class Person(var name:String, private var age:Int){ print(“….") }
在构造该Person对象时,会同时打印出其中的语句。
如果类名之后没有参数,则具备一个无参主构造器,这样一个构造器仅仅是简单地执行类体中的所有语句而已。主构造器中的参数也可以不带val/var,这取决于后续其他方法是否使用该字段,如果没有使用仅当做是局部变量,如果使用了该字段就升级为类型中字段。
对象
scala中没有静态方法或静态字段,可以使用object这个语法结构来达到同样的目的,对象定义了某个类的单个实例,对象使用object来定义而非class,可以将下面的类定义想象成静态工具类方法,用于产生JVM内部唯一的unique数字:
object Accounts { private var lastNumber = 0 def newUniqueNumber() = { lastNumber += 1 lastNumber } }
对象在本职上可以拥有类的所有特性——甚至可以扩展其他类或者特质,但不能提供构造器函数。任何在Java中使用单例对象的地方,在scala中都可以用对象来实现:
- 作为存放工具函数或常量的地方;
- 高效地共享单个不可变实例;
- 需要用单个实例来协调某个服务时;
在Java中,经常需要用到既有实例方法又有静态方法的类,在scala中,可以通过类和类同名的伴生对象来达到同样的目的,就好比Java中既存在静态方法又存在实例方法一样。类和它的伴生对象可以互相访问其私有特性,它们必须存在于同一个源文件中。
一个object可以扩展类以及一个或多个特质(trait),其最终结果是一个扩展了指定类以及特质的类对象,同时拥有在对象定义中给出的所有特性,此时该实例在JVM中就为同一个实例存在。
我们通常会定义和使用对象的apply方法,当遇到下面类型的表达式,apply方法就会被调用,通常这样的一个apply方法返回的是伴生类对象:
Object(参数1, 参数2,...)
对于嵌套表达式而言,这种方式省去了new关键字,会方便很多。注意,Array(100)和new Array(100)很容易混淆,前者调用的是apply方法,后者调用的是构造器。
每个scala程序都必须从一个对象的main方法开始,这个方法的签名类似:
def main(args: Array[String]) { }
除了每次都提供main方法之外,还可以扩展app特质,将程序代码放入构造器方法体内,如果需要命令行参数,可以通过args来得到:
object Hello extends App{ println(“Hello!") }
如果在调用该应用程序时设置了-Dscala.time选项的话,程序在退出时会显示逝去时间。
和Java不同,scala并没有枚举类型,不过标准类库中提供了一个Enumeration助手类,用于产出枚举。
object TrafficLightColor extends Enumeration { val Red, Yellow, Green = Value }
记住枚举的类型为TrafficLightColor.Value,可以使用import TrafficLightColor._来静态导入所有枚举值。
特质
scala和java一样不允许类从多个超类继承,因为对于多重继承来说的代价非常之高。Java采取了非常强的限制策略,类只能扩展自一个超类,可以实现任意数量的接口,但接口只能包含抽象方法,不能包含字段,所以在Java中我们经常看到同时提供接口和抽象基类的做法。
scala中提供特质而非接口,特质可以同时拥有抽象方法和具体方法,而类可以实现多个特质,这个设计干净利落地解决了Java接口的问题。
trait的定义很简单,类似Java接口:
trait Logger { def log(msg: String) }
子类实现时使用extends而非implements:
class ConsoleLogger extends Logger{ override def log(msg: String): Unit = {println(msg)} }
在重写特质的抽象方法时不需要给出override关键字,如果需要的特质不止一个,需要用with关键字来添加额外的特质(所有Java接口都可以当做scala的特质使用)。
特质的方法并不一定需要是抽象的,注意如果实现具有带实现的特质时,可以说得到了一个具体的实现方法,这在Java接口中是无法做到的,也可以说被混入了。注意让特质拥有具体行为存在一个弊端,当特质改变时,所有混入了该特质的类都必须要重新编译。
trait可以在对象定义时才被“混入”到对象中,这无疑进一步省略了一个java class定义(相比于内部类或匿名内部类),注意被混入的trait需要有着具体方法实现,这样在SavingAccount类中就可以在运行时才决定使用的trait:
class SavingAccount extends Account with Logger{ override def withdraw(amount: Double): Unit = { if(amount > 1000) log("Insufficient funds") } } val acct = new SavingAccount with ConsoleLogger
此外,特质还可以叠加,可以为类或对象添加多个互相调用的特质,从最后一个开始,这对于需要分阶段加工处理某个值的场景非常有用,从设计模式角度,这个非常类似于Java中的装饰者模式(Decorator,继承同样的接口,叠加不同的实现)。
额外增加两个trait实现:
trait ShortLogger extends Logger{ val maxLength = 15 override def log(msg: String): Unit ={ super.log(if(msg.length <= maxLength) msg else msg.substring(0, maxLength - 3)) } } trait TimestampLogger extends Logger{ override def log(msg: String): Unit = { super.log(new java.util.Date() + " " + msg) } }
在定义时,使用两个特质进行叠加到ConsoleLogger中,注意,我们在定义ShortLogger/TimestampLogger时,使用的都是super.log,这样就会将修改过的msg传入到ConsoleLogger中,执行的顺序取决于定义的顺序,限制性ShortLogger,再执行TimestampLogger,此种定义使用时ShortLogger执行的super.log会调用TimestampLogger,同样TimestampLogger的super.log也会调用到ConsoleLogger。
val acct = new SavingAccount with ConsoleLogger with TimestampLogger with ShortLogger acct.withdraw(1001)
可以非常方便地在对象声明处修改顺序,这好比在语言层面上增加了AOP功能。
对特质而言,无法从源码判断super.someMethod会执行到哪里,确切的方法依赖于使用这些特质的对象或类给出的顺序,要灵活得多。如果需要控制具体哪一个特质的方法被调用,可以在括号中给出名称: super[ConsoleLogger].log(…),这里给出的类型必须是超类型,无法使用继承层次中更远的特质或类。
特质中可以包含大量工具方法,而这些工具方法可以依赖一些抽象方法来实现,with一个特质,在实现中大量使用特质中的方法,到对象创建时才去指定特质的具体实现。从Java的实际模式角度,这可以看成是策略模式(Strategy,可替换的算法实现)的直接语言层面实现。
当然,特质也会有构造器,特质的构造器以如下方式运行:
- 调用超类的构造器;
- 特质构造器在超类构造器之后,类构造器之前执行;
- 特质由左到右被构造;
- 每个特质当中,父特质先被构造;
- 如果多个特质共有一个父特质,而那个父特质已经被构造,则不会再次构造;
- 所有特质构造完毕,子类被构造。
下面的类被声明:
class SavingAccount extends Account with FileLogger with ShortLogger
构造器的执行顺序:1.Account(超类);2.Logger(第一个特质的父类);3.FileLogger(父类);4.ShortLogger(第二个特质,由于其超类已经被构造过,跳过);5.SavingAccount。
特质不能有构造器参数,每个特质都有一个无参数的构造器,缺少构造器参数是特质与类之间唯一的技术差别,除此之外特质可以具备类的所有特性。
相关推荐
零基础学习scala 全面的scala教程整理 零基础学习scala 全面的scala教程整理
Scala语言的上述特点和学习动机,以及必要的环境配置和基础语法,是初学者入门Scala的基石。对于有一定Java基础的人来说,Scala能够提供更加高效和简洁的编程体验,尤其在处理大规模数据处理和复杂系统开发时显示出...
Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,被广泛应用于大数据...通过这个项目,学习者不仅能掌握Scala的基本语法和概念,还能熟悉Spark框架的应用,从而在大数据领域建立起坚实的基础。
总的来说,这个Scala学习课件全面覆盖了从基础到高级的Scala编程知识,并且特别强调了在Spark环境下的应用。通过深入学习和实践,你不仅可以掌握Scala语言,还能有效利用Scala在大数据分析和处理项目中发挥出Spark的...
1. Scala基础知识:这包括Scala的基本语法、数据类型、控制结构等。例如,"Getting Started" 部分通常会指导读者如何设置Scala控制台和集成开发环境(IDE),比如IntelliJ IDEA或Eclipse。这部分内容还会引导你编写...
在"Scala-学习资料-mht.rar"这个压缩包中,包含了关于Scala的学习资料,格式为MHT(单一文件网页),这种格式通常用于保存完整的网页内容,包括文本、图像和样式表。 首先,我们来了解一下Scala的基础知识。Scala这...
【大数据课程-Scala编程基础-1.Scala语言初识】是针对初学者设计的一门课程,旨在教授如何入门Scala编程,特别适合已有Java基础的学员。Scala是一种在2001年由洛桑联邦理工学院(EPFL)的编程方法实验室研发的语言,...
在“Scala基础.pdf”中,我们可能会涵盖以下几个核心知识点: 1. **基本语法**:Scala的语法与Java有所不同,但也有相似之处。它支持变量声明(val和var)、常量(final val)、类、对象、包和导入等基本概念。学习...
它详细介绍了Scala的各种高级特性,适合有了一定编程基础并希望深入了解Scala内部机制的学习者。 另外,“快学Scala”的PDF电子书也是一个很好的入门资源。这本书将Scala的很多基础概念和实践方法进行了通俗易懂的...
第一部分:"Scala入门及进阶-part01-基础知识.pdf" 涵盖了Scala的基础概念。在这里,你会学习到Scala的安装与环境配置,理解Scala的基本语法,包括变量声明、数据类型(如基本类型、引用类型和集合类型)、控制结构...
这个压缩包“scala学习资料(带书签)”提供了一个全面的学习路径,从基础到高级,帮助你深入理解和掌握Scala语言。 **入门篇** 1. **基础语法**:Scala的基础包括变量声明、类型系统、控制结构(如if/else、循环)...
读书笔记:快速入手的Scala基础语法学习笔记
这个"scala学习源代码"的压缩包文件很可能包含了用于教学或自我学习Scala编程的基础示例。让我们深入了解一下Scala语言的关键概念和特性。 首先,Scala运行在Java虚拟机(JVM)上,这意味着它可以无缝地与Java库...
scala学习视频资料以及讲义,从基础的环境配置开始讲起,以及后面具体案例开发.适合新手学习,还有具体讲义对照复习查看。
1. **Scala基础** - **基本语法**:Scala的基础语法与Java类似,但更简洁。包括变量声明(val和var)、常量、数据类型(如Int、Double、String等)以及表达式和语句。 - **类和对象**:Scala中的类和对象是面向...
### Scala基础知识概述 #### 一、Scala语言简介 Scala是一种多范式的编程语言,它结合了面向对象编程和函数式编程的特点。Scala运行在Java平台上,兼容Java代码,并且能够利用JVM的强大功能。Scala的设计目标是简洁...
### Scala学习笔记(全) #### 一、Scala概述与特点 Scala是一种多范式的编程语言,旨在集成面向对象编程和函数式编程的各种特性。它运行于Java平台(Java虚拟机JVM),并且能够完全兼容所有的Java程序。这使得Scala...
Scala学习资源Scala编程语言抓住了很多开发者的眼球。如果你粗略浏览Scala的网站,你会觉得Scala是一种纯粹的面向对象编程语言,而又无缝地结合了命令式编程和函数式编程风格。Christopher Diggins认为: 不太久...