Scala

Scala

特性

面向对象特性

Scala是一种纯面向对象的语言,每个值都是对象。对象的数据类型以及行为由类和特质描述。

函数式编程

Scala也是一种函数式语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。Scala的case class及其内置的模式匹配相当于函数式编程语言中常用的代数类型。

静态类型

Scala具备类型系统,通过编译时检查,保证代码的安全性和一致性

扩展性

Scala提供了许多独特的语言机制,可以以库的形式轻易无缝添加新的语言结构:

  • 任何方法可用作前缀或后缀操作符
  • 可以根据预期类型自动构造闭包

并发性

Scala使用Actor作为其并发模型,Actor是类似线程的实体,通过邮箱发收消息。Actor可以复用线程,因此可以在程序中可以使用数百万个Actor

基础语法

关键字

在这里插入图片描述

在scala中不能使用以上关键字作为变量

换行符

scala是面向行的语言,语句可以用分号(;)结束或换行

scala程序里语句末尾的分号通常是可选的

scala包

使用package关键字定义包

使用import关键字引用包

数据类型

scala与java有着相同的数据类型

下列数据类型都是对象,在scala中可以对数字等基础类型调用方法的
在这里插入图片描述

多行字符串使用三个双引号表示分隔符,格式为(""" … “”")

变量

在scala中,使用var定义变量,使用val定义常量

//变量申明
//varName:变量名   DataType:数据类型  Initial Value:初始值
var varName:DataType[=Initial Value]
//常量声明
val varName:DataType[=Initial Value]

声明变量时,若不指定数据类型,就需要给出初始值(数据类型可以通过初始值推断出来)

访问修饰符

默认情况下Scala对象访问级别是public

private

在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员

用private关键字修饰,带有此标记的成员仅在包含成员定义的类或对象内部可见

class Outer{
    class Inner{
        private def f(){
            println("f function")
        }
        class InnerMost{
            f()  //能正确访问
        }
    }
    (new Inner).f()   //错误访问
}

因为f()方法在Inner类中被声明为private,而 (new Inner).f()访问在Inner类之外,所以访问不合法

protect

只允许保护成员在定义了该成员的类的子类中被访问

package p{
class Super{
    protected def f() {println("f")}
    }
        class Sub extends Super{
            f()  //正确
        }
        class Other{
                (new Super).f() //错误
        }
}

public

scala中默认访问修饰符为public,这样的成员在任何地方都可以被访问

class Outer {
   class Inner {
      def f() { println("f") }
      class InnerMost {
         f() // 正确
      }
   }
   (new Inner).f() // 正确因为 f() 是 public
}

方法与函数

scala中方法和java定义类似,是组成类的一部分

scala中的函数是一个对象可以赋值给一个白能量,函数则是一个完整的对象,其实就是继承了Trait的类的对象

scala中使用val语句定义函数,使用def语句定义方法

class Test{
    def m(x:Int) = x + 3
    val f = (x:Int) => x + 3
}

方法声明:

def function([参数列表]) : [return type]

如果方法后没有等号和方法体,该方法被隐式声明为抽象(abstract)

方法定义:

使用def关键字,紧接着是可选的参数列表,一个冒号和方法的返回类型,一个等号,最后是方法的主体

//return type可以是任意合法的scala数据类型
//参数列表中的参数可以使用逗号分隔
def function([参数列表])[return type] ={
    function body
    return [expr]
}
//将两个传入的参数相加并求和
object Add{
    def addInt(a:Int,b:Int):Int ={
        var sum:Int = 0
        sum = a + b
        return sum
    }
}

如果方法没有返回值,可以返回Unit(和Java的void类似)

object Hello{
    def sayHello:Unit={
        println("hello scala")
    }
}
可变参数

通过在参数的类型之后放一个星号来设置可变参数(参数类型一致)

def printString(args:String*)={
	var i:Int = 0
	for(arg <- args){
	    println("arg value["+i+"]="+arg)
	    i = i +1
	}
}
默认参数

在未传递参数时,函数会调用默认参数值,若传递参数则传递值会取代默认值

object Test{
    def main(args:Array[String]){
        //调用方法时未传递参数,使用默认值
        println("返回值为"+addInt())
    }
    def addInt(a:Int=5,b:Int=6):Int={
        var sum = 0
        sum = a + b
        return sum
    }
}
//执行结果=》返回值为11

当函数同时包含普通参数和默认参数时,无默认参数的在前,默认参数在后

def defaultAddInt(c:Int,a:Int=5,b:Int=6):Int={
    function body
}
递归函数

函数可以调用它本身

object Test{
    def main(args:Array[String]){
        for(i <- 1 to 10){
            println(i+"的阶乘为:"+factorial(i))
        }
    }
    def factorial(n:BigInt):BigInt={
        if(n <= 1)
          1
        else
        n * factorial(n-1)
    }
}
匿名函数

定义:箭头左边是参数列表,右边是函数体

//定义一个接受Int类型输入参数的匿名函数
var inc = (x:Int) => x+1
//此时inc可作为一个函数被调用
var x = inc(7)-1

//无参数的匿名函数
var userDir = () => {println("scala")}

闭包

闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量

通常来讲,可以简单认为是访问一个函数里面局部变量的另外一个函数

object Test{
	def main(args:Array[String]){
		println( "muliplier(1) value = " +  multiplier(1) )  
      	println( "muliplier(2) value = " +  multiplier(2) )  
	}
	//自由变量,定义在函数外面
	var factor = 3
	//muliplier引用到函数外面定义的变量,成为一个“闭包”
	val muliplier = (i:Int) => i * factor
}

字符串

在scala中,字符串的类型实际上是 Java String

在scala中,String是一个不可变的对象,所以该对象不可被修改,意味着如果修改字符串就会产生一个新的字符串

创建字符串

var greeting = "Hello World!"
//或者
var greeting:String = "Hello World!"

String对象是不可变的,如果需要创建一个可变字符串使用StringBuilder类

var buf = new StringBuilder
//char类型使用单引号
buf += 'a'
//拼接字符串这里  使用双加号++=
buf ++= "bc"

字符串长度

使用length()获取字符串长度

var str = "www.baidu.com"
println("长度为"+str.length())

字符串连接

String类中使用concat()来连接两个字符串

同样也可以使用加号(+)来连接

//定义
string1.concat(string2)
def stringConcat(){
    var str1 = "hello"
    var str2 = "scala"
    println(str1.concat(str2))
    println(str1 + str2)
}

数组

数组用来存储固定大小的同类型元素

数组的第一个元素索引为0

数组声明

var arr:Array[String] = new Array[String](3)
//或者
var arr = new Array[String](3)
//或者
var arr = Array("Baidu","Tenxun","Alibaba")

数组处理

import Array._
object Test{
    def main(args:Array[String]){
        var myList = Array(1,2,3,4,5)
        //输出数组所有元素
        for(x <- myList){
            println(x)
        }
        //计算数组所有元素的总和
        var total = 0
        for(i <- 0 to (myList.length - 1)){
            total += myList[i]
        }
        println("数组总和为"+total)
        //查找数组中最大元素
        var max = myList[0]
        for(i <- 0 to (myList.length - 1)){
            if(myList[i] > max){
                max = myList[i]
            }
        }
        println("最大值为"+max)
    }
}

多维数组

矩阵和表格是我们常见的二维数组

//二维数组定义
var arr = Array.ofDim[Int](3,3)
//二维数组处理
import Array._
object Test{
    def main(args:Array[String]){
        var arr = Array.ofDim[Int](3,3,)
        //创建矩阵
        for(i <- 0 to 2){
            for(j <- 0 to 2){
                arr(i)(j) = j
            }
        }
        //打印二维矩阵
        for(i <- 0 to 2){
            for(j <- 0 to 2){
                println(" "+arr(i)(j))
            }
            println()
        }
    }
}

合并数组

使用concat()方法来合并两个数组

import Array._
object Test{
    def main(args:Array[String]){
        var arr1 = Array(1,2,3,4)
        var arr2 = Array(5,6,7,8)
        var arr3 = concat(arr1,arr2)
        //输出所有数组元素
        for(i <- arr3.length){
            println(i)
        }
    }
}

区间数组

使用range()方法生成范围内的数组,range()方法最后一个参数为步长,默认步长为1

object Test{
    def main(args:Array[String]){
        var arr1 = range(10,20,2)
        var arr2 = range(10,20)
        //输出所有元素
        for(i <- arr1){
            println(" "+ i )
        }
        println()
        for(i <- arr2){
            println(" "+ i )
        }
    }
}

数组常用方法

scala使用处理数组的方法前,需要import Array._ 引入包

在这里插入图片描述

集合(Collection)

可变集合:可以修改、添加、移除集合中的元素

不可变集合:集合不会改变,任然可以模拟添加、移除或更新操作,只是返回一个新的集合,原集合不会发生改变

List列表

列表时不可变的,值一旦定义就不能改变

列表的元素类型T可以写成List[T]

//字符串列表
val strList:List[String] = List("scala","spark")
//整型列表
val numList:List[Int] = List(1,2,3)
//空列表
val emptyList:List[Nothing] = List()
//二维列表
val arrList:List[List[Int]]=List(
	List(1,0,0)
    List(0,1,0)
    List(0,0,1)
)

构造列表的两个基本单位:Nil和 ::

Nil也可以表示为空列表

//字符串列表
val strList = "scala"::("spark"::Nil )
//整型列表
val numList = 1::(2::(3::Nil))
//空列表
val emptyList = Nil
//二维列表
val arrList = (1::(0::(0::Nil)))::
              (0::(1::(0::Nil)))::
              (0::(0::(1::Nil)))::Nil
基本操作

(1)head:返回列表第一个元素

(2)tail:返回一个列表,包含除了第一个元素之外的其他元素

(3)isEmpty:在列表为空时返回true

object Test{
    def main(args:Array[String]){
        val strList = "scala"::("spark"::Nil )
        val numList = Nil
        println("第一个单词:"+ strList.head)
        println("其他单词为:"+ strList.tail)
        println("整型列表是否为空"+numList.isEmpty)
    }
}
连接列表

可以使用三冒号(:::)或:::()方法或concat()方法来连接两个或多个列表

object Test {
   def main(args: Array[String]) {
      val site1 = "Runoob" :: ("Google" :: ("Baidu" :: Nil))
      val site2 = "Facebook" :: ("Taobao" :: Nil)

      // 使用 ::: 运算符
      var fruit = site1 ::: site2
      println( "site1 ::: site2 : " + fruit )
     
      // 使用 List.:::() 方法
      fruit = site1.:::(site2)
      println( "site1.:::(site2) : " + fruit )

      // 使用 concat 方法
      fruit = List.concat(site1, site2)
      println( "List.concat(site1, site2) : " + fruit  )
   }
}
指定创建重复元素

使用fill()方法可以指定列表中元素的重复次数

object Test {
   def main(args: Array[String]) {
      val site = List.fill(3)("Runoob") // 重复 Runoob 3次
      println( "site : " + site  )
       //site : List(Runoob, Runoob, Runoob)

      val num = List.fill(5)(2)         // 重复元素 2, 10 次
      println( "num : " + num  )
       //num : List(2, 2, 2, 2, 2)
   }
}
指定函数创建列表

使用tabulate()方法可以通过指定函数来创建列表

参数:第一个表示元素数量,可以是二维的

​ 第二个表示指定的函数,通过函数计算结果并返回值插入到列表中,起始值为0

object Test{
	def mian(args:Array[String]){
        //通过指定函数创建5个元素的列表
        val oneList = List.tabulate(6)(n=>n*n)
        println("一维列表"+oneList)
        //创建二维列表
        //(_*_):是(x,y => x*y)的简写模式
        val twoList = List.tabulate(4,5)(_*_)
        println("二维列表"+twoList)
    }
}
列表反转

使用reverse()方法将列表的顺序反转

object Test {
   def main(args: Array[String]) {
      val site = "Runoob" :: ("Google" :: ("Baidu" :: Nil))
      println( "site 反转前 : " + site )
	 	
      println( "site 反转后 : " + site.reverse )
   }
}

Set集合

没有重复的对象集合,所有元素都是唯一的

默认下使用的是不可变集合(scala.collection.immutable.Set)

若要可变集合,引入scala.collection.mutable.Set包

基本操作

(1)head:返回列表第一个元素

(2)tail:返回一个列表,包含除了第一个元素之外的其他元素

(3)isEmpty:在列表为空时返回true

object Test{
    def main(args:Array[String]){
        val strSet = Set("scala","spark")
        val numSet:Set[Int] = Set()
        println("第一个单词:"+ strSet.head)
        println("其他单词为:"+ strSet.tail)
        println("整型列表是否为空"+numSet.isEmpty)
    }
}
连接集合

使用++运算符或++()方法连接两个Set集合,会移除重复元素

object Test {
   def main(args: Array[String]) {
      val site1 = Set("Runoob", "Google", "Baidu")
      val site2 = Set("Faceboook", "Taobao")

      // ++ 作为运算符使用
      var site = site1 ++ site2
      println( "site1 ++ site2 : " + site )

      //  ++ 作为方法使用
      site = site1.++(site2)
      println( "site1.++(site2) : " + site )
   }
}
查找最大与最小元素

使用min()查找最小元素,使用max()查找最大元素

object Test {
   def main(args: Array[String]) {
      val num = Set(5,6,9,20,30,45)

      // 查找集合中最大与最小元素
      println( "Set(5,6,9,20,30,45) 集合中的最小元素是 : " + num.min )
      println( "Set(5,6,9,20,30,45) 集合中的最大元素是 : " + num.max )
   }
}
交集

使用&()或者intersect()方法查看两个集合交集元素

object Test {
   def main(args: Array[String]) {
      val num1 = Set(5,6,9,20,30,45)
      val num2 = Set(50,60,9,20,35,55)

      // 交集
      println( "num1.&(num2) : " + num1.&(num2) )
      println( "num1.intersect(num2) : " + num1.intersect(num2) )
   }
}

Map映射

是一种可迭代的键值对(key-value)结构

键是唯一的,Map也叫哈希表(Hash table)

// 空哈希表,键为字符串,值为整型
var A:Map[Char,Int] = Map()

// Map 键值对演示
val colors = Map("red" -> "#FF0000", "azure" -> "#F0FFFF")
基本操作

(1)keys:返回map中所有的键(key)

(2)values:返回map所有的值(value)

(3)isEmpty:在map为空时返回true

object Test {
   def main(args: Array[String]) {
      val colors = Map("red" -> "#FF0000","azure" -> "#F0FFFF", "peru" -> "#CD853F")
      val nums: Map[Int, Int] = Map()

      println( "colors 中的键为 : " + colors.keys )
      println( "colors 中的值为 : " + colors.values )
      println( "检测 colors 是否为空 : " + colors.isEmpty )
      println( "检测 nums 是否为空 : " + nums.isEmpty )
   }
}
合并map

使用++运算符或者++()方法连接两个map,会删除重复key

相同的key对应的value会被右边的Map中的值替代

object Test {
   def main(args: Array[String]) {
      val colors1 = Map("red" -> "#FF0000", "azure" -> "#F0FFFF", "peru" -> "#CD853F")
      val colors2 = Map("blue" -> "#0033FF", "yellow" -> "#FFFF00","red" -> "#FF0000")

      //  ++ 作为运算符
      var colors = colors1 ++ colors2
      println( "colors1 ++ colors2 : " + colors )

      //  ++ 作为方法
      colors = colors1.++(colors2)
      println( "colors1.++(colors2) : " + colors )

   }
}
获取K-V

通过foreach获取map的keys和values

object Test{
    def main(args:Array[String]){
        val strMap = Map("scala"->"sc","spark->sp")
        strMap.keys.foreach{i => println("key="+i) println("value="+strMap(i))}
    }
}
查看key是否存在

通过contain()方法查看map中是否存在指定key

object Test {
   def main(args: Array[String]) {
      val strMap = Map("scala"->"sc","spark->sp")

      if( strMap.contains( "scala" )){
           println("scala 键存在,对应的值为 :"  + strMap("scala"))
      }else{
           println("scala 键不存在")
      }
   }
}

Tuple元组

与列表一样,元组也是不可变的,可以包含不同类型的元素,元组的值是通过将单个值包含在圆括号中构成

val tu = (1,3.14,"scala")
//或者
val tu = new Tuple(1,3.14,"scala")

访问元组元素

可以使用t._1访问第一个元素,使用t._2访问第二个元素

object Test{
    def main(args:Array[String]){
        val tu = (1,2,3,4)
        val sum = t._1+t._2+t._3+t._4
        println("元素和为:"+sum)
    }
}
迭代元组

使用Tuple.productiterator()方法来迭代输出元组所有元素

object Test {
   def main(args: Array[String]) {
      val tu = (4,3,2,1)
     
      tu.productIterator.foreach{ i =>println("Value = " + i )}
   }
}
元组转字符串

使用Tuple.toString()方法将元组所有元素转换成字符串

object Test {
   def main(args: Array[String]) {
      val t = new Tuple3(1, "hello", Console)
     
      println("连接后的字符串为: " + t.toString() )
   }
}
元素交换

使用Tuple.swap()方法交换元组元素

object Test {
   def main(args: Array[String]) {
      val t = new Tuple2("www.google.com", "www.runoob.com")
     
      println("交换后的元组: " + t.swap )
   }
}

Option选项

用来表示一个值是可选的(有值或无值)

Option[T]是一个类型为T的可选值的类型。如果值存在,Option[T]就是一个Some[T];如果不存在,Option[T]就是对象None

val myMap: Map[String, String] = Map("key1" -> "value")
val value1: Option[String] = myMap.get("key1")
val value2: Option[String] = myMap.get("key2")
 
println(value1) // Some("value1")
println(value2) // None

迭代器(Iterator)

用于访问集合的方法

基本操作

(1)next():返回迭代器的下一个元素,并且更新迭代器的状态

(2)hasNext():用于检测集合中是否还有元素

让迭代器it逐个返回所有元素最佳单的方法是使用while循环

object Test {
   def main(args: Array[String]) {
      val it = Iterator("Baidu", "Google", "Runoob", "Taobao")
     
      while (it.hasNext){
         println(it.next())
      }
   }
}

类和对象

类是对象的抽象,而对象是类的具体实例

类是抽象的不占用内存,而对象是具体的占用存储空间

继承

(1)重写一个非抽象方法必须使用override修饰符

(2)只有主构造函数才可以往基类的构造函数里写参数

class Point(xc: Int, yc: Int) {
   var x: Int = xc
   var y: Int = yc

   def move(dx: Int, dy: Int) {
      x = x + dx
      y = y + dy
      println ("x 的坐标点: " + x);
      println ("y 的坐标点: " + y);
   }
}
//override val xc为重写了父类的字段
//使用extends关键字表示继承
class Location(override val xc: Int, override val yc: Int,val zc :Int) extends Point(xc, yc){
   var z: Int = zc

   def move(dx: Int, dy: Int, dz: Int) {
      x = x + dx
      y = y + dy
      z = z + dz
      println ("x 的坐标点 : " + x);
      println ("y 的坐标点 : " + y);
      println ("z 的坐标点 : " + z);
   }
}

Scala只允许继承一个父类

单例对象

在Scala中是没有static的

使用object关键字实现单例模式

单例模式中,除了定义的类之外,还需定义一个同名的object对象,object对象不能带参数

当单例对象与某个类名称相同时,称为这个类的伴生对象(companion object),必须在同一个源文件里定义类和他的伴生对象。类被称为这个单例对象的伴生类(companion class)。类和他的伴生对象可以互相访问其私有成员

// 私有构造方法
class Marker private(val color:String) {

  println("创建" + this)
 
  override def toString(): String = "颜色标记:"+ color
 
}

// 伴生对象,与类名字相同,可以访问类的私有属性和方法
object Marker{
 
    private val markers: Map[String, Marker] = Map(
      "red" -> new Marker("red"),
      "blue" -> new Marker("blue"),
      "green" -> new Marker("green")
    )
   
    def apply(color:String) = {
      if(markers.contains(color)) markers(color) else null
    }
 
   
    def getMarker(color:String) = {
      if(markers.contains(color)) markers(color) else null
    }
    def main(args: Array[String]) {
        println(Marker("red"))  
        // 单例函数调用,省略了.(点)符号  
                println(Marker getMarker "blue")  
    }
}

特征Trait

相当于Java的接口,实际上比接口功能强大

特征还可以定义属性和方法的实现

特征(Trait)定义方式与类相似,使用trait关键字

要使用trait中定义的方法,需要先继承(可继承多个特征)

//triat定义特征
//特征中,可以选择性定义方法实现(类比Java抽象类)
trait Equal {
  def isEqual(x: Any): Boolean
  def isNotEqual(x: Any): Boolean = !isEqual(x)
}
//使用extends继承特征,用于使用特征中定义的方法
class Point(xc: Int, yc: Int) extends Equal {
  var x: Int = xc
  var y: Int = yc
  def isEqual(obj: Any) =
    obj.isInstanceOf[Point] &&
    obj.asInstanceOf[Point].x == x
}

object Test {
   def main(args: Array[String]) {
      val p1 = new Point(2, 3)
      val p2 = new Point(2, 4)
      val p3 = new Point(3, 3)

      println(p1.isNotEqual(p2))
      println(p1.isNotEqual(p3))
      println(p1.isNotEqual(2))
   }
}

特征构造顺序

特征也可以有构造器,由字段的初始化和其他特征体的语句构成

构造器执行顺序:

(1)调用超类的构造器

(2)特征构造器在超类构造器之后、类构造器之前执行

(3)特征由左到右被构造

(4)每个特征中,父特征先被构造

(5)如果多个特征中共有一个父特征,该父特征只会被构造一次

(6)所有特征被构造完毕,子类被构造

模式匹配

模式匹配包含了一系列备选项(使用关键字case修饰)

格式:选择器match{备选项}

只要发现一个匹配的case,剩下的case就不会继续匹配

object Test{
    def main(args:Array[String]){
        println(matchTest(3))//other
    }
    def matchTest(x:Int):String = x match{
        case 1 => "one"
        case 2 => "two"
        case 3 => "three"
        case _ => "other"
    }
}
样例类

使用case关键字修饰的类,经过优化用于模式匹配

object Test {
   def main(args: Array[String]) {
        val alice = new Person("Alice", 25)
        val bob = new Person("Bob", 32)
        val charlie = new Person("Charlie", 32)
   
    for (person <- List(alice, bob, charlie)) {
        person match {
            case Person("Alice", 25) => println("Hi Alice!")
            case Person("Bob", 32) => println("Hi Bob!")
            case Person(name, age) =>
               println("Age: " + age + " year, name: " + name + "?")
         }
      }
   }
   // 样例类
   case class Person(name: String, age: Int)
}

声明样例类时发生下列过程

(1)构造器的每个参数变成了val

(2)在伴生对象中提供了apply方法,所以可以不使用new关键字就可以构建对象

(3)提供unapply方法使模式匹配可以工作

(4)生成tpString、eqauls、hashCode和copy方法

正则表达式

通过导入scala.util.matching.Regex包支持

import scala.util.matching.Regex

object Test {
   def main(args: Array[String]) {
       //使用String类的r()方法构建Regex对象
       //可以直接new Regex("str")构建Regex对象
      val pattern = "Scala".r
      val str = "Scala is Scalable and cool"
     
       //使用findFirstIn找到首个匹配项
      println(pattern findFirstIn str)
       //输出Some(Scala)
   }
}

将匹配文本替换:

使用replaceFirstIn()方法替换第一个匹配项,使用replaceAllIn()替换所有匹配项

object Test {
   def main(args: Array[String]) {
   	  //通过new Regex()构建对象	
      val pattern = new Regex("(S|s)cala") 
      val str = "Scala is scalable and cool"
     
      println(pattern replaceFirstIn(str, "Java"))
   }
}

异常处理

抛出异常:

throw new IllegalArgumentException

捕获异常:

使用模式匹配思想来在catch中捕获异常(在catch中是一系列case选项)

object Test {
   def main(args: Array[String]) {
      try {
         val f = new FileReader("input.txt")
      } catch {
         case ex: FileNotFoundException =>{
            println("Missing file exception")
         }
         case ex: IOException => {
            println("IO Exception")
         }
      }
   }
}

提取器(Extracor)

提取器是从传递给它的对象中提取出构造该对象的参数

Scala提取器是一个带有unapply()方法的对象,unapplyu接受一个对象,然后从对象中提取值,提取的值通常是用来构造该对象的值

object Test {
   def main(args: Array[String]) {
      //Apply 方法 : Zara@gmail.com
      println ("Apply 方法 : " + apply("Zara", "gmail.com"));
       //Unapply 方法 : Some((Zara,gmail.com))
      println ("Unapply 方法 : " + unapply("Zara@gmail.com"));
       //Unapply 方法 : None
      println ("Unapply 方法 : " + unapply("Zara Ali"));

   }
   // 注入方法 (可选)
   def apply(user: String, domain: String) = {
      user +"@"+ domain
   }

   // 提取方法(必选)
   def unapply(str: String): Option[(String, String)] = {
      val parts = str split "@"
      if (parts.length == 2){
         Some(parts(0), parts(1))
      }else{
         None
      }
   }
}

提取器使用模式匹配:

object Test {
   def main(args: Array[String]) {
     //通过apply()方法实例化对象
      val x = Test(5)
      println(x)

      x match
      {
         case Test(num) => println(x + " 是 " + num + " 的两倍!")
         //unapply 被调用
         case _ => println("无法计算")
      }

   }
   def apply(x: Int) = x*2
   def unapply(z: Int): Option[Int] = if (z%2==0) Some(z/2) else None
}

通过apply()方法我们无需使用new关键字来构建对象

文件IO

scala进行文件读写操作,直接用的是java中的IO类(java.io.File)

import java.io._

object Test {
   def main(args: Array[String]) {
      val writer = new PrintWriter(new File("test.txt" ))

      writer.write("hello scala")
      writer.close()
   }
}

读取用户输入

使用scala.io.StdIn类

import scala.io._
object Test {
   def main(args: Array[String]) {
      print("请输入 : " )
      val line = StdIn.readLine()

      println("谢谢,你输入的是: " + line)
   }
}

读取文件内容

通过Scala的Source类及伴生对象来读取文件

import scala.io.Source
object Test{
    def main(args:Array[String]){
        println("文件内容为:")
        Source.fromFile("test.txt").foreach{
            print
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值