Scala基础

在Scala中,几乎所有的语言元素都是表达式。

println("hello wolrd")

是一个表达式,

"hello"+" world"

也是一个表达式。

可以通过val定义一个常量,亦可以通过var定义一个变量。推荐多使用常量。

声明 def

可以使用def来定义一个函数。函数体是一个表达式。

使用Block表达式的时候,默认最后一行的返回是返回值,无需显式指定。

函数还可以像值一样,赋值给var或val。因此函数也可以作为参数传给另一个函数。

def square(a: Int) = a * a



def squareWithBlock(a: Int) = {

    a * a

}



val squareVal = (a: Int) => a * a



def addOne(f: Int => Int, arg: Int) = f(arg) + 1



println("square(2):" + square(2))

println("squareWithBlock(2):" + squareWithBlock(2))

println("squareVal(2):" + squareVal(2))

println("addOne(squareVal,2):" + addOne(squareVal, 2))

借贷模式

由于函数可以像值一样作为参数传递,所以可以方便的实现借贷模式。

这个例子是从/proc/self/stat文件中读取当前进程的pid。

withScanner封装了try-finally块,所以调用者不用再close。

注:当表达式没有返回值时,默认返回Unit。

import scala.reflect.io.File

import java.util.Scanner



def withScanner(f: File, op: Scanner => Unit) = {

    val scanner = new Scanner(f.bufferedReader)

    try {

        op(scanner)

    } finally {

        scanner.close()

    }

}



withScanner(File("/proc/self/stat"),

    scanner => println("pid is " + scanner.next()))

按名称传递参数

这个例子演示了按名称传递参数,由于有除以0,所以运行该程序会产生异常。

val logEnable = false



def log(msg: String) =

    if (logEnable) println(msg)



val MSG = "programing is running"



log(MSG + 1 / 0)

试着将

def log(msg: String)

修改为

def log(msg: => String)

由按值传递修改为按名称传递后将不会产生异常。

因为log函数的参数是按名称传递,参数会等到实际使用的时候才会计算,所以被跳过。

按名称传递参数可以减少不必要的计算和异常。

定义类

可以用class关键字来定义类。并通过new来创建类。

在定义类时可以定义字段,如firstName,lastName。这样做还可以自动生成构造函数。

可以在类中通过def定义函数。var和val定义字段。

class Persion(val firstName: String, val lastName: String) {



    private var _age = 0

    def age = _age

    def age_=(newAge: Int) = _age = newAge



    def fullName() = firstName + " " + lastName



    override def toString() = fullName()

}



val obama: Persion = new Persion("Barack", "Obama")



println("Persion: " + obama)

println("firstName: " + obama.firstName)

println("lastName: " + obama.lastName)

obama.age_=(51)

println("age: " + obama.age)

函数名是任何字符如+,-,*,/。

试着将

obama.age_=(51)

简化为

obama.age = 51

这样的简化更像调用一个变量。

鸭子类型

走起来像鸭子,叫起来像鸭子,就是鸭子。

def withClose(closeAble: { def close(): Unit }, 

    op: { def close(): Unit } => Unit) {

    try {

        op(closeAble)

    } finally {

        closeAble.close()

    }

}



class Connection {

    def close() = println("close Connection")

}



val conn: Connection = new Connection()

withClose(conn, conn =>

println("do something with Connection"))

这个例子中使用

{ def close(): Unit }

作为参数类型。因此任何含有close()的函数的类都可以作为参数。

不必使用继承这种不够灵活的特性。

柯里化

这个例子和上面的功能相同。不同的是使用了柯里化(Currying)技术。

def withClose(closeAble: { def close(): Unit })

    (op: { def close(): Unit } => Unit) {

    try {

        op(closeAble)

    } finally {

        closeAble.close()

    }

}



class Connection {

    def close() = println("close Connection")

}



val conn: Connection = new Connection()

withClose(conn)(conn =>

    println("do something with Connection"))
def add(x:Int, y:Int) = x + y

是普通的函数

def add(x:Int) = (y:Int) => x + y

是柯里化后的函数,相当于返回一个匿名函数表达式。

 def add(x:Int)(y:Int) = x + y

是简化写法

柯里化可以让我们构造出更像原生语言提供的功能的代码

试着将例子中的withclose(…)(…)换成withclose(…){…}

范型

之前的例子可以使用泛型变得更简洁更灵活。

def withClose[A <: { def close(): Unit }, B](closeAble: A)

  (f: A => B): B =

  try {

    f(closeAble)

  } finally {

    closeAble.close()

  }

class Connection {

  def close() = println("close Connection")

}

val conn: Connection = new Connection()

val msg = withClose(conn) { conn =>

  {

    println("do something with Connection")

    "123456"

  }

}



println(msg)

试着将

"123456"

修改为

123456

虽然msg由String类型变为Int类型,但是由于使用了泛型,代码依旧可以正常运行。

Traits

Traits就像是有函数体的Interface。使用with关键字来混入。

trait ForEachAble[A] {

  def iterator: java.util.Iterator[A]

  def foreach(f: A => Unit) = {

    val iter = iterator

    while (iter.hasNext)

      f(iter.next)

  }

}



trait JsonAble {

  def toJson() =

    scala.util.parsing.json.JSONFormat.defaultFormatter(this)

}



val list = new java.util.ArrayList[Int]() with ForEachAble[Int] 

list.add(1); list.add(2)



println("For each: "); list.foreach(x => println(x))

//println("Json: " + list.toJson())

这个例子是给java.util.ArrayList添加了foreach的功能。

试着再在with ForEachAble[Int]后面加上

with JsonAble

给list添加toJson的能力

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值