Scala 概要教程

包引用

  所有Scala类(class)和对象(object)都必须放置在软件包中,而软件包必须在Scala源代码文件的开头声明和命名。下面的代码声明了Claim Check样本的源代码文件位于claimcheck软件包中

 package co.vaughnvernon.reactiveenterprise.claimcheck

  如果你想使用其他源代码文件或软件包中定义的类、对象和其他Scala数据类型,就必须使用import 语句引用它们。Scala语言的import语句与Java的import 语句非常相似。

import akka.actor.Actor
import akka.actor.Props
//或者
import akka.actor
类声明

  应该在Scala源代码文件中添加什么内容呢?首先,就像Java和C#支持类一样,Scala语言也支持类并对该功能做了一点提高。

class ItemChecker{}
abstract class ItemContainer{}
class ShoppingCart extends ItemContainer{}

  第一个定义的类(Itemchecker)不会扩展任何特定的基类。另一方面,shoppingCart 扩展了抽象基类Itemcontainer。此处没有介绍这些类的细节。Itemchecker和shoppingcart类都具有的特点之一是,都拥有无参数构造器。这意味着可以使用下面的方式实例化shoppingcart类:

val shoppingcart=new ShoppingCart()
变量声明

  如果shoppingcart是一个var变量,那么完全可以对其进行反复赋值。

var shoppingCart=new ShoppingCart 
val differentCart=new ShoppingCartshoppingcart=differentcart//该表达式有效

  注意,在这两个shoppingcart变量声明语句中,并没有确切地指定数据类型,仅指定了引用。这是因为可以通过Scala语言的类型推断功能解决这些麻烦。类型推断是指Scala编译器能够分析代码,并检测出隐含的数据类型。该功能得出的结果与以明确方式声明类型的作用相同。

val shoppingCart:ShoppingCart=new ShoppingCart
构造器

  这里展示了为shoppingcart类添加构造器参数的方式(使用Scala 语言调用类参数的方式):

class ShoppingCart(val maximumItems:Int)extends ItemContainer{}
伴生对象

  伴生对象是Scala语言中的一个特殊概念,而且它永远都会是单例对象;换言之,程序中仅会存在一个该类型的对象。在本例中,Defaultcatalog是一个类,而它的伴生对象就像一个工厂,用于获取Defaultcatalog实例。当然,伴生对象还能够完成其他任务。

  下面是一段简单的实现代码:

object DefaultCatalog{
  def apply=new DefaultCatalog(catalogConfig)
  def name=catalogConfig.name
}

  当你使用Defaultcatalog()表达式时,apply方法就会被调用,如上面的例子所示。apply方法仅会返回一个DefaultCatalog类的新实例,而不会要求客户端必须了解catalogconfig参数的情况。可以在伴生对象中定义任何种类的方法(如name)。为了使用该方法,客户端会通过下面的方式使用伴生对象:

val catalogName=DefaultCatalog.name

  这种方式没有问题,但使用伴生对象的动机是什么呢?Scala不支持静态方法,因此伴生对象提供了对其伴生类所需的各种工厂和实用方法的支持。

object DefaultCatalog{
  def apply:Catalog={
    new DefaultCatalog(catalogConfig)
    def name:String={}
  }
}

  catalogConfig.name不仅可以使用花括号封装代码块,还可以通过在引用后面添加:type,声明方法会返回哪种类型的数据。明确声明方法返回数据的类型是最好的Scala编程习惯。app1y引用的代码块会返回Catalog类型的实例,而name引用的代码块会返回string类型的实例。

操作符

  如果你使用过Java,可能会因无法将符号用作方法的名称而感到有一点遗憾。Scala改变了这一点,在Scala中使用操作符甚至比在C++中更方便。当然,不应滥用这个功能。没有限制,自由也不会存在。例如,在Scala中可以将!用作方法的名称。

def!(message:Any):Unit={}

  实际上,下面是一种发送Akka消息的方式:

actor!SomeMessage()

  使用!方法的方式与使用te11()方法的方式相同。而且,还不需要在接收者actor对象后面加圆点,也不需要使用括号将参数SomeMessage()括起来,这使代码更易于阅读得多。

特征(接口)

  Scala源代码文件中还可以定义特征(trait)。Scala中的特征有点像Java和C#中的接口和抽象类。它像一种接口,会在内部定义为使用它们的类的对象定义协议。它还与抽象类相似,因为特征内部至少会有一部分拥有默认的实现代码。从这方面看,特征就是一种抽象类。如果特征被使用了,那么它就会变成抽象类。事实上,多重特征可以由单个类实现或扩展。该操作通常称为混入多重特征。

class ShoppingCart(
val catalogSource:CatalogSource,val maximumItems:Int)
extends ItemBrowser with ItemContainer{}
样本类

  前面介绍过Scala类的种类与Java和C#中类的种类相似。除了那些相似的类外,Scala还有一种样本类(case class)。

case class ProcessOrder(orderId:String)
val message=ProcessOrder("123")
循环和迭代

  此刻你可能想知道Scala是怎样支持循环和迭代操作的。实际上,Scala提供了非常多的循环方式。本书仅会列举几个示例。下面是编写for循环的一种方式:

for(counter <-1 to 20){
print1n(counter)//变量counter每次都被赋予1至20之间的新值

  使用for表达式可以轻松迭代集合。

 for(element <-Vector(1,2,3,4,5)){
    print1n(element)//element变量每次都被赋予1至5之间的新值

for(element <-Vector(1,2,3,4,5)){
    print1n(element)//element变量每次都被赋予1至5之间的新值

  你可以使用集合本身提供的迭代操作,还可以提供处理每个集合元素的闭包。
vector(1,2,3,4,5)map{element =>println(element)}

  下面的示例使用了for推导语句:

val numbers=Vector(1,2,3,4,5,6,7,8,9,10)
val evenNumbers=for(number<-numbers){
    if(number%2==0)
}yield number

  还可以通过另一种方式获得相同的结果,即使用更为简洁的Scala代码:

val evenNumbers=
for{
    number<-numbers if number%2==0
}yield number
泛型

  如果你想完整地声明evenNumbers引用,可使用下面的方式:

val evenNumbers:Vector[Int]=..…

  这段代码声明了一个类型为Int的Vector集合。Java和C#使用尖括号表示泛型(即<type>),与Java和C#不同,Scala使用方括号表示泛型(即<type>)。

模式匹配

  模式匹配功能是Scala中功能最强大的工具之一,可以在多种环境(如由数字元素组成的集合中)中使用它。

Vector(1,2,3)map{
case 1=>print1n("One")//显式编号为1的单词
case 2=>print1n("Two")//显式编号为2的单词
case 3=>print1n("Three")//显式编号为3的单词

  执行匹配操作时不必对集合进行迭代。对单个对象也可以进行模式匹配,在下面的例子中该单个对象为10。

10 match{
  case 1=>println("One")
  case 2=>println("Two")
  case 3=>println("Three")
  case =>print1n("Several")//显示默认的匹配单词
}

类型匹配

case class ConfigureProcessor(orderProvider: OrderProvider, timeOut: Long)
case class ProcessOrder(orderId: String)

val message=ProcessOrder("123")
message match{
case config: ConfigureProcessor=> configureProcessor(init)
case processOrder: ProcessOrder=>
    val order=orderFor(processOrder. orderId)
...
}

类型与参数匹配

message match{
case ConfiqureProcessor(orderProvider,timeOut)=>
    configureProcessor(orderProvider,timeOut)
case ProcessOrder(orderId)=>
    val order=orderFor(orderId)
...
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容