‘壹’ Scala这个有知道的吗,怎么样啊
Scala是一门多范式语言,一般常用的范式有:命令式 和 函数式,由于Scala是一门多范式语言,所以通俗来说我们可以说Scala是一门命令式编程语言同时也是函数式编程语言。
命令式:命令式是植根于冯·诺依曼体系的,一个命令式程序就是一个冯·诺依曼机的指令序列,给机器提供一条又一条的命令序列让其原封不动的执行。通俗来说就是按照指令顺序一步一步执行。
函数式:又称泛函编程,它将计算机的计算视为数据中的函数计算。函数式编程最重要的基础是λ(lambda)演算,λ演算对函数式编程语言有着巨大的影响。典型的函数式语言包括Erlang和Lisp等。
为什么要用函数式:
目前来说CPU的性能发展大体上是在同等面积上集成更多的晶体管等集成电路,随着纳米技术的不断提高,CPU能够集成的计算单元也越来越多,但终归是有上限的。所以在之后,单核的发展逐渐走向了多核的发展,以多核来达到性能的提升。
目前计算机的CPU基本上都是多核CPU,在使用命令式编程的时候就设涉及到多线程之间的状态共享,需要锁机制实现并发的控制,而锁机制虽然保证了安全性,但是却对性能来说是一个阻碍。
而函数式编程不会再多个线程之间共享状态,不需要用锁机制,可以更好的并行处理,充分利用多核CPU的并行处理能力。
如,电信行业多数使用Erlang来进行开发,就是看中了函数式编程的并行处理能力。
Scala的特点
Scala是面向对象的:Scala是一个纯面向对象语言,在某种意义上来讲所有数值都是对象。对象的类型和行为是由class和trait来描述的。Class的抽象可由子类化和一种灵活的基于mixin的组合机制(它可作为多重继承的简单替代方案)来扩展。
Scala是函数式的: Scala还是一个函数式语言,在某种意义上来讲所有函数都是数值。Scala为定义匿名函数提供了一种轻量级的语法,它支持高阶(higher- order)函数、允许函数嵌套、支持局部套用(currying)。Scala的case类及其内置支持的模式匹配模型代数类型在许多函数式编程语言中 都被使用。
Scala是静态类型的:Scala配备了一套富有表现力的类型系统,该抽象概念以一种安全的和一致的方式被使用。
Scala是可扩展的:Scala的设计承认了实践事实,领域特定应用开发通常需要领域特定语言扩展。Scala提供了一个独特的语言组合机制,这可以更加容易地以类库的形式增加新的语言结构:两者结合使用可方便地定义新语句,无需扩展语法,也无需使用类似宏的元编程工具。
任何方式可以被用作中缀(infix)或后缀(postfix)操作符
闭包按照所期望的类型(目标类型)自动地被构造
Scala可与java和.NET进行互操作:Scala 设计时就考虑了与流行编程环境良好交互,如Java 2运行时环境(JRE)和 .NET框架(CLR)。特别是与主流面向对象语言,如Java和C#尽量无缝交互。Scala有像Java和C#一样的编译模型(独立编译,动态装载 类),允许访问成千上万的高质量类库。
‘贰’ Scala编程语言简介
Scala编程语言近来抓住了很多开发者的眼球 如果你粗略浏览Scala的网站 你会觉得Scala是一种纯粹的面向对象编程语言 而又无缝地结合了命令式和函数式的编程风格 Christopher Diggins认为
不太久之前编程语言还可以毫无疑义地归类成 命令式 或者 函数式 Scala代表了一个新的语言品种 它抹平了这些人为划分的界限
根据David Rupp在博客中的说法 Scala可能是下下一代Java 这么高的评价让人不禁想看看它到底是什么东西
Scala有几项关键特性表明了它的面向对象的本质 例如 Scala中的每个值都是一个对象 包括基本数据类型(即布尔值 数字等)在内 连函数也是对象 另外 类可以被子类化 而且Scala还提供了基于mixin的乎迟让组合(mixin based position)
与只支持单继承的语言相比 Scala具有更广泛意义上的类重用 Scala允许定义新类的时候重用 一个类中新增的成员定义(即相较于其父类的差异之处) Scala称之为mixin类组合
Scala还包含了若干函数式语言的关键概念 包括高阶函数(Higher Order Function) 局部套用(Currying) 嵌套函数(Nested Function) 序列解读(Sequence Comprehensions)等等
Scala是静态类型的 这就允许它提供泛型类 内部类 甚至多态方法(Polymorphic Method) 另外值得一提的是 Scala被特意设计成能够与Java和 NET互操作 Scala当前版本还不能在 NET上运行(虽然上一版可以) 但按照计划将来可以在 NET上运行
Scala可以与Java互操作 它用scalac这个编译器把源文件编译成Java的class文件(即在JVM上运行的字节码) 你可以从Scala中调用所有的Java类库 也同样可以从Java应用程序中调用Scala的代码 用David Rupp的话来说
它也可以访问现存的数之不尽的Java类库 这让(潜在地)迁移到Scala更加容易
这让Scala得以使用为Java 或者 编写的巨量的Java类库和框架 Scala会经常性地针对这几个版本的Java进行测试 Scala可能也可以在更早版本的Java上运行 但没有经过正式的测试 Scala以BSD许可发布 并且数年前就已经被认为相当稳定了
说了这么多 我们还没有回答一个问题 为什么我要使用Scala? Scala的设计始终贯穿着一个理念
创造一种更好地支持组件的语言 (《The Scala Programming Language》 Donna Malayeri)
也就是说软件应该由可重用的部件构造而成 Scala旨在提供一种编程语言 能够统一和一般化分别来自面向对象和函数式两种不同风格的关键概念岁局
借着这个目标与设计 Scala得以提供一些出众的特性 包括
* 面旦丛向对象风格
* 函数式风格
* 更高层的并发模型
Scala把Erlang风格的基于actor的并发带进了JVM 开发者现在可以利用Scala的actor模型在JVM上设计具伸缩性的并发应用程序 它会自动获得多核心处理器带来的优势 而不必依照复杂的Java线程模型来编写程序
* 轻量级的函数语法
o 高阶
o 嵌套
o 局部套用(Currying)
o 匿名
* 与XML集成
o 可在Scala程序中直接书写XML
o 可将XML转换成Scala类
* 与Java无缝地互操作
Scala的风格和特性已经吸引了大量的开发者 比如Debasish Ghosh就觉得
我已经把玩了Scala好一阵子 可以说我绝对享受这个语言的创新之处
lishixin/Article/program/Java/hx/201311/26873
‘叁’ 编译后生成的scala文件扩展名为
Java 源程序文件编译后产生的文件称为(字节码)文件,其扩展名为(.class)。
‘肆’ scala manifest和classmanifest的区别
Manifest是scala2.8引入的一个特质,用于编译器在运行时也能获取泛型类型的信息。在JVM上,泛型参数类型T在运行时是被“擦拭”掉的,编译器把T当作Object来对待,所以T的具体信息是无法得到的;为了使得在运行时得到T的信息,scala需要额外通过Manifest来存储T的信息,并作为参数用在方法的运行时上下文。
def test[T] (x:T, m:Manifest[T]) { ... }
有了Manifest[T]这个记录T类型信息的参数m,在运行时就可以根据m来更准确的判断T了。但如果每个方法都这么写,让方法的调用者要额外传入m参数,非常不友好,且对方法的设计是一道伤疤。好在scala中有隐式转换、隐式参数的功能,在这个地方可以用隐式参数来减轻调用者的麻烦。
获取class manifests的两种基本方式:
1 def classOf[T <: Any](implicit m: scala.reflect.Manifest[T]): Class[T] = m.erasure.asInstanceOf[Class[T]
通过implicit m: scala.reflect.Manifest[T]声明一个隐式参数,这样scala编译器能在编译时提供T的类型信息了
2 def classOf[T <: Any : Manifest] : Class[T] = manifest[T].erasure.asInstanceOf[Class[T]
其中 T <: Any : Manifest,拆分成两部分来看
T <: Any
T 是Any的子类型(即可以是任意基本类型scala.AnyVal 和引用类型 scala.AnyRef)
T : Manifest 相当于对classOf 方法currying
隐式增加参数列表如下:(implicit evidence$1: Manifest[T]),
通过manifest[T] 方法即可获取Manifest实例
可见形式1 和形式2实质是一样的。
应用:
1最常见的是获取类型参数的Class,形如someMethod[Type]
如akka中源码: def actorOf[T <: Actor : Manifest]: ActorRef = actorOf(manifest[T].erasure.asInstanceOf[Class[_ <: Actor])
class Worker extends Actor {
def receive = {
case Work(start, nrOfElements) =>
self reply Result(calculatePiFor(start, nrOfElements)) // perform the work
}
}
就可以如此使用了: val workerActorRef = actorOf[Worker]
2 编程方式创建范型数组
def evenElems[T: ClassManifest](xs: Vector[T]): Array[T] = {
val arr = new Array[T]((xs.length + 1) / 2)
for (i <- 0 until xs.length by 2)
arr(i / 2) = xs(i)
arr
}
scala> evenElems(Vector("a","b","c"))
res: Array[java.lang.String] = Array(a, c)