Scala 概述

Scala名称是scalable language,表明可扩展性较强

  • 面向对象编程和函数式编程的结合
  • Scala代码被编译成Java字节码,运行在JVM上,可以调用已有的Java代码
  • 方便进行并发和同步处理

面向对象

任何值都是一个对象,任何操作都是一个方法调用

1 + 2//实际上是:Int类调用+方法

函数式语言

  • 函数是 first-class values,就像int和String类型,可用作为其他函数的参数,返回值,可以赋值存储在变量中

数据,函数,类等的类型分为三类
First Class 该类型的值可以作为函数的参数和返回值,也可以赋给变量。
Second Class 该类型的值可以作为函数的参数,但不能从函数返回,也不能赋给变量。(C/C++ 中的函数指针)
Third Class 该类型的值作为函数参数也不行

  • 输入值处理后映射到新的输出值,不改变原数据,即不可变数据结构(immutable data structure),或者说方法不产生副作用,即引用透明(reference transparent

副作用:side effect,改变方法外部的的变量状态或者执行I/O操作,返回值为空的函数都有副作用,副作用是不可避免的,但是可以尽可能的减少此类函数


特点

  • 兼容性
    Scala可以和Java无缝对接,调用Java的方法,访问字段,继承类,实现接口等,不需要其他的语法,Java代码也可以调用Scala代码
    重用了很多Java的类型,也对一些类型进行了增强,通过隐式转换来实现扩展的高级操作和Java原有操作的兼容
  • 简洁
    Scala是同样的Java代码行数的一半左右
    避免了一些样板式的语法,类型推断减少了重复的类型信息,大量的库代码可以直接使用,特别是traits,便于构建一个类
// Java 类定义
  class MyClass {

      private int index;
      private String name;

      public MyClass(int index, String name) {
          this.index = index;
          this.name = name;
      }
  }

//等同的Scala类定义
  class MyClass(index: Int, name: String)
  • 高阶 high-level
//name中是否包含大写字母
val nameHasUpperCase = name.exists(_.isUpper)//_.isUpper是函数字面量,或者叫做匿名函数

//Java 8中的写法
boolean nameHasUpperCase =
    name.chars().anyMatch(
        (int ch) -> Character.isUpperCase((char) ch)
    );

可以使用其他函数作为参数,轻量,容易理解和重构,引用透明

s.exists(p) || s.exists(q) 等价 s.exists(x => p(x) || q(x)) 
  • 静态类型
    指在编译时进行类型检查
    Scala的类型系统通过类型推断避免冗长,通过模式匹配以及其他几种新方法保证灵活性
    属性验证:静态系统通过类型检查,避免某些运行错误,减少需要类型检查的次数
    安全重构:修改代码,正确率更高,例如更改函数名称,修改参数等
    文档:编译器和IDE可以提供更多的帮助,例如根据类型进行代码提示

起源

Scala采用了大量的Java和C#语法,他们大部分又来自C和C ++的语法。 表达式,语句,块,类,包和导入等语法大都类似Java,同时Scala也采用了Java的基本类型,库及其执行模型等。此外也借鉴了许多其他的语言,例如Ruby,Algol,Simula,ML等
同时Scala也有自己的创新,例如抽象类型abstract types,特质traits,提取器extractors等


语法概览

定义变量

有两种类型的变量valvarval类似于Java中的final变量, 一旦初始化,不能被重新赋值,
var可以重新赋值

Scala的解释器或编译器可以推断类型

scala> val msg = "Hello, world!"
msg: String = Hello, world!

scala> val msg2: java.lang.String = "Hello again, world!"//显式指定类型
msg2: String = Hello again, world!

定义函数

函数开头是def关键字,之后是函数名,圆括号内是通过逗号分隔的参数列表,参数的类型必须指定(不会进行类型推断),冒号后跟返回类型,之后是等号后跟一对花括号,内部是函数体(函数相当于返回一个数值的表达式块)

def max(x: Int, y: Int): Int = {
    //Scala的 if 语句可以返回一个值
    if (x > y) 
        x
    else 
        y
}
基本的函数定义形式

函数参数类型是val,不能重新赋值
返回类型可以推断时,可以省略,没有返回值对应Unit类型(Java中的void类型)
函数只有一条语句,花括号可以省略

匿名函数

也叫作函数字面量(function literal),通常作为函数的参数进行传递


匿名函数语法
//功能相同的遍历打印语句
args.foreach(arg => println(arg))
args.foreach((arg: String) => println(arg))
args.foreach(println) //对应函数为带一个参数的一条语句

for (arg <- args)
    println(arg)

数组

访问数组中的元素,索引放在圆括号内val类型的数组本身的内容是可变的

val greetStrings = new Array[String](3)
//初始化每个元素
greetStrings(0) = "Hello" 
greetStrings(1) = ", "
greetStrings(2) = "world!\n"
for (i <- 0 to 2)
    print(greetStrings(i))

//等价于 
greetStrings.update(0, "Hello")
greetStrings.update(1, ", ")
greetStrings.update(2, "world!\n")
for (i <- 0.to(2))
    print(greetStrings.apply(i))

0 to 2 对应方法调用 (0).to(2)如果方法只有一个参数,则可以不带圆点或圆括号,但是必须指定方法调用的调用方

Scala没有运算符重载,因为它实际上并没有传统意义上的运算符,但是可以在方法名称中使用+, -, *, /等字符
访问:将包含一个或多个值的括号应用于变量时,Scala会将代码转换为调用该变量名为apply的方法
赋值:当对包含圆括号的变量进行赋值时,编译器会将其转换为update的方法,该方法将括号中的参数以及等号右侧的对象作为参数

更简单的方法,等同调用伴生对象的apply工厂方法

val numNames = Array("zero", "one", "two")//等价于Array.apply("zero", "one", "two")

链表 List

类型相同的不可变对象序列scala.List

// ::: 是连接两个链表 concatenation
val oneTwo = List(1, 2)
val threeFour = List(3, 4)
val oneTwoThreeFour = oneTwo ::: threeFour

//空链表用List() 或者 Nil 表示
val oneTwoThree = 1 :: 2 :: 3 :: Nil

运算符函数,通常是在左操作数上调用该方法,例如a.*(b), 但是如果方法名以冒号结尾,则在右操作数上调用该方法,例如threeFour.:::(oneTwo)

元组 Tuple

类型可以不同的不可变对象容器
要实例化一个包含某些对象的新元组,只需将对象放在括号中,并用逗号分隔,之后可以用._N(从1开始索引)访问

val pair = (99, "Luftballons")
println(pair._1)
println(pair._2)

Set/Map

集合库分为可变集合和不可变集合两种类型。 例如,数组总是可变的,列表总是不变的。 Scala还为Set/Map提供了可变和不可变的库,并且简单名称相同,完全限定名称不同,因为每个名称都位于不同的包中

var jetSet = Set("Boeing", "Airbus")  //本质上调用apply方法,默认是immutable类型
jetSet += "Lear" //等同jetSet = jetSet + "Lear"
println(jetSet.contains("Cessna"))

如果使用mutable类型

import scala.collection.mutable
val movieSet = mutable.Set("Hitch", "Poltergeist")
movieSet += "Shrek" //调用方法 += : movieSet.+=("Shrek")
println(movieSet)

明确使用HashSet

import scala.collection.immutable.HashSet
val hashSet = HashSet("Tomatoes", "Chilies")

Map的情况:

import scala.collection.mutable
val treasureMap = mutable.Map[Int, String]()
treasureMap += (1 -> "Go to island.")
treasureMap += (2 -> "Find big X on ground.")
treasureMap += (3 -> "Dig.")
println(treasureMap(2))

Scala程序中的任何对象上调用->方法,返回一个包含键和值的双元素元组

默认immutable的情况

val romanNumeral = Map(1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V")
println(romanNumeral(4))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容