Scala编程的基础知识

Scala是一个面向对象的函数式编程语言,在Scala中,一切皆函数。

函数式编程的优点:

  • 提高生产效率,代码量更小。
  • 更容易编写多并发或多进程的应用。
  • 带来更少的bug,代码量小了,bug自然就小了。

Scala是一门基于JVM的静态语言,和Java能够无缝隙操作。尽管Scala是一门混合了面向对象编程和函数式编程的语言,但是它还是侧重于函数式编程。

Scala的安装

由于Scala是基于JVM的静态语言,所以安装Scala之前需要安装Java环境。安装步骤可以参考 【菜鸟教程】的链接:http://www.runoob.com/scala/scala-install.html

基础类型


这是要注意,Scala并没有基本数据类型,Scala的每一个基础类型都是一个类。在编译阶段,Scala编译器会自动将Scala基础类型转换为Java基本类型。

关键:Scala的基础类型的首字母都是大写的,如果写成小写会出现编译错误,这真是一个奇葩的特点。

变量

Scala有两种类型的变量:

  • 可变变量,使用var定义。
  • 不可变变量,使用val定义。

可变变量可以多次赋值:

var a=20
a=10

而不可变变量,初始化后不能再重新赋值:

val b=10

对于函数式编程,最好不要使用可变变量。

函数

在Scala中,函数和变量没有什么区别,它可以作为变量的值,可以在其他函数体中定义,可以作为函数的返回值,可以作为函数的参数。

Scala中用关键字def来定义函数。

def add(a:Int, b:Int): Int={
      val sum=a+b
      return sum
}

add是函数名;括号中的ab是形参,Int是形参类型;括号外的lnt是函数返回值类型;接着一个=号跟着大括号是函数体。

Scala中每条语句可以由分号;结尾,也可以不写,当然不写是最方便的,怎么方便怎么来。

方法

方法是指类的成员函数,这一点和c++/Java类似。

局部函数

在其他函数或者方法中定义的函数称为局部函数,它只在其定义的函数内可见,即只有局部可见性。

高阶方法

把函数作为输入参数的方法称为高阶方法。类似的,高阶函数是指把函数作为参数的函数。

一个高阶函数的例子:

def encode(n: Int, f:(Int) => Long): Long ={
      val x=n*10
      f(x)
}

函数encode接收两个参数,返回一个Long类型的值。一个参数是Int类型;另一个参数是函数f函数f接收一个Int类型的参数,返回的是Long类型的值

函数字面量

函数字面量是指源代码中的匿名函数,它可以作为高阶方法或高阶函数的参数,也可以赋值给变量。

函数字面量的定义由处于圆括号中的输入函数列表、右箭头和函数体构成,下面是一个函数字面量的例子:

(x: Int) => {
      x+100
}

闭包

闭包就是可以使用非局部变量的函数字面量。

类是面向对象编程的重要概念,是一组具有相同属性和行为的事物的抽象。Scala中的类和Java类似,它由字段和方法组成,字段就是属性,方法就是行为函数。

Scala使用关键字class来定义一个类, 在Scala中的类没有访问控制这种操作,更为简洁:

class Car(mk: String, ml: String, cr: String){
    val make=mk  
    val model=ml  
    var color=cr  
    def repaint(newColor: String) = {  
        color=newColor
    }
}

类的实例使用关键字new创建

val mustang=new Car("Ford", "Mustang", "Red")

因为Scala运行在JVM之上,所以不用显示删除对象,Java的垃圾回收器会自动删除那些不再使用的对象。

单例

在面向对象编程中一个常见的设计模式就是单例,它是指那些只可以实例化一次的类。Scala中使用关键字object来定义单例对象

object DatabaseConnection{
    def open(name: String) : Int ={
        ...
    }
    def read(streamId: Int) : Array[Byte] = {
        ...
    }
    def close(): Unit={
        ...
    }
 }

样本类

样本类是指使用case修饰符的类,例如:

case class Message(from: String, to: String, content: String)

对于样本类,Scala提供了一些语法上的便利

  • 不必使用关键字new就可以创建样本类的实例
  • 样本类参数列表中的所有参数隐式获得val前缀
  • 支持模式匹配

模式匹配

模式匹配是Scala中的概念,它类似于其他语言的switch语句。考虑一个以颜色的字符串作为参数的简单函数:

def colorToNumber(color: String): Int ={
    val num=color match{
        case "Red" => 1
        case "Blue"=> 2
        case "Green"=> 3
        case "Yellow" => 4
        case _ =>0
    }
    return num
}

模式匹配的几个特性:

  • Scala使用关键字match代替关键字switch
  • 下划线代表默认选项。
  • 每一个选项不需要break语句,匹配选项后,其他的选项不会被执行。
  • 每一个选项对应一个表达式,每个表达式返回一个值。

操作符

Scala没有内置操作符,在Scala中,每个基础类型都是一个类,每一个操作符都是一个方法。使用操作符等价于调用方法。例如:

val a=10
val b=20
val c=a+b 

这里的并不是Scala的内置操作符,它是定义在Int类中的一个方法。Scala允许以操作符的方式来调用方法。

特征

Scala的特征类似于Java中的接口,然而,不同于Java接口,Scala的特征可以有方法的实现,而且它还可以有字段。

特征看上去像抽象类,它们都有字段和方法。区别在于一个类只能继承一个抽象类,但可以继承多个特征。

Scala中的特征使用关键字trait定义:

trait Shape{
    def area(): Int
}
class Square(length: Int) extends Shape{
    def area=length*length
}
class Rectangle(length: Int, width: Int) extends Shape{
    def area=length*width
}
val square = new Square(10)
val area = square.area

元组

元组是一个容器,用于存放多个不同类型的元素,它是不可变的。即创建元组之后,便不可修改。

元组是一个用小括号括起来的大杂烩:

val a=(10, true, "harry")

元组的下标从1开始的,访问元组的元素如下:

println(a._1)
println(a._2)

为什么下标数字前面有一个碍眼的下划线??鬼知道这种骚操作是为何。反正没下划线就会报错~

Option类型

Option是一种数据类型,用来表示值是可选的,即要么无值要么有值。它要么是样本类some的实例,要么是单例对象None的实例。

Option类型可以在函数或方法中作为值返回。返回some(x)表示有值,返回None表示无值。从函数返回的Option类型对象可以用于模式匹配中:

def colorCode(color: String): Option[Int] ={
    color match{
        case "Red" => Some(1)
        case "Blue"=> Some(2)
        case "Green"=> Some(3)
        case "Yellow" => Some(4)
        case _ => None
    }
}
val code = colorCode("orange")
code match{
    case Some(c) => println("code for orange is: " + c)
    case None => println("code not defined for orange")
}

使用Option类型有助于避免空指针异常。

集合

集合是一种容器类的数据结构。Scala有丰富的集合类,集合类包含各种类型,所有的集合类都有同样的接口。

Scala的集合类可以分为三类:

  • 序列
  • 集合
  • map

序列

序列表示有先后次序的元素序列,可根据位置来访问集合中的元素。
序列又分为三种:

  • 数组
  • 列表
  • 向量
数组Array

数组是有索引的元素序列,所有的元素的数据类型相同,数组是可变的,可以修改元素但不能增加元素,即数组是定长的。

Scala中的数组类似于其他语言的数组,数组索引从0开始,通过索引访问或修改元素:

val arr = Array(10, 20, 30 ,40)
println(arr(0))
列表List

列表是一个线性的元素序列,存放一堆数据类型相同的元素,列表是不可变的,即创建后不可修改。

创建列表的几种方法:

val a=List(10, 20, 30)
val b=(1 to 100).toList
val c=someArray.toList

关于列表的几种操作:

  • 访问第一个元素使用head方法
  • 访问第一个元素之后的所有元素使用tail方法
  • 判断列表是否为空,使用isEmpty方法。当列表为空时返回true
向量Vector

向量是结合了列表和数组的优点的类,根据索引访问元素占用固定的时间。向量支持快速修改和访问任意位置的元素:

val v1 = Vector(0, 10, 20, 30)
val v2 = v1 :+ 50  // 在向量末尾添加元素50
val v3 = v1(3)

集合Set

集合是一个无序的集合,且每个元素都不同,没用索引。

val f = Set(1, 2, 3 ) 

集合支持两种基本操作:

  • contains: 如果集合中包含这个元素,则返回true,并将这个元素作为参数传递过来
  • isEmpty: 如果当前集合为空,则返回true

map

map是一个键-值对集合,在其他语言中,map也叫做字典。即根据键找出相应的值。

val a = Map("USA" -> "zhazha", "UK" -> "London", "India" -> "New Delhi")
val indiaCapital = a("India")

注意:Scala的各种集合类都是使用小括号,没有中括号和大括号!

集合类上的高阶方法

Scala集合的强大之处就在于这些高阶方法,这些高阶方法把函数当做参数。

map方法

map方法的参数是一个函数,它将这个函数作用于集合中的每一个元素,返回由其返回值所组成的集合。

val xs = List(1, 2, 3, 4)
val ys = xs.map((x: Int) => x*10.0)
println(ys)

输出如下:

scala> println(ys)
List(10.0, 20.0, 30.0, 40.0)

flatMap

Scala集合的flatMap方法类似于map,它的参数是一个函数,它把这个函数作用于集合中的每一个元素,返回另外一个集合。

val line = "Scala is fun"
val SingleSpace = " "
val words = line.split(SingleSpace)
val array = words.flatMap(_.toList)
array

输出结果为:

scala> array
res4: Array[Char] = Array(S, c, a, l, a, i, s, f, u, n)

Scala版的hello world

一个单独的Scala应用程序需要一个具有main方法的单例对象。这个main方法以一个Array[String]类型的参数作为输入,它不需要返回值,它是这个Scala程序的入口,这个有main方法的单例可以随便起名。

object HelloWorld{
    /*
    这是我的第一个Scala程序
    */
    def main(args: Array[String]){
        println("hello world!") // 输出hello world
    }
 }

Scala源代码文件以.scala作为后缀名,依照惯例,一般以代码中的赖明或者单例名作为文件名,比如上面的代码文件应该命名为HelloWorld.scala

这篇文章写了一天,终于写完了。

每天学习一点点,每天进步一点点。

你可能感兴趣的:(Scala编程的基础知识)