Scala学习笔记(一)

一、定义变量

    Scala 为定义变量提供了两种语法。使用 val定义常量,一经定义后,该变量名不能被重新赋值。使用 var定义变量,可被重新赋值。

package com.sunsharing

/**
  * Created by Administrator on 2016/1/24.
  */
object Variable {
  var i=0;
  val j=0;
  i = 999;
  j = 888;
}

报错:

Scala学习笔记(一)_第1张图片

二、定义函数

    函数的定义也非常简单,使用关键字 def,后跟函数名和参数列表,如果不是递归函数可以选择省略函数返回类型。Scala 还支持定义匿名函数,匿名函数由参数列表,箭头连接符和函数体组成。函数在 Scala 中属于一级对象,它可以作为参数传递给其他函数,可以作为另一个函数的返回值,或者赋给一个变量。在下面的示例代码中,定义的匿名函数被赋给变量 cube。匿名函数使用起来非常方便,比如 List对象中的一些方法需要传入一个简单的函数作为参数,我们当然可以定义一个函数,然后再传给 List对象中的方法,但使用匿名函数,程序看上去更加简洁。

package com.sunsharing

/**
  * Created by Administrator on 2016/1/24.
  */
object ScalaStudy {
  // 定义函数
  def square(x: Int): Int =
    x * x
  // 如果不是递归函数,函数返回类型可省略
  def sum_of_square(x: Int, y: Int) =
    square(x) + square(y)

  def main(args: Array[String]): Unit = {

    println("平方和", sum_of_square(2, 3))

    // 定义匿名函数
    val cube = (x: Int) => x * x *x
    println("立方", cube(3))

    // 使用匿名函数,返回列表中的正数
    println("正数列表", List(-2, -1, 0, 1, 2, 3).filter(x => x > 0))
  }



}

运行结果:

(平方和,13)
(立方,27)
(正数列表,List(1, 2, 3))

与Java对比:

    首先,函数体没有像 Java 那样放在 {}里。Scala 中的一条语句其实是一个表达式,函数的执行过程就是对函数体内的表达式的求值过程,最后一条表达式的值就是函数的返回值。如果函数体只包含一条表达式,则可以省略 {}。其次,没有显示的 return语句,最后一条表达式的值会自动返回给函数的调用者。

    和 Java 不同,在 Scala 中,函数内部还可以定义其他函数。比如上面的程序中,如果用户只对 sum_of_square 函数感兴趣,则我们可以将 square 函数定义为内部函数,实现细节的隐藏。

三、流程控制语句

/**
  * if else 求绝对值
  * @param n
  * @return
  */
 def abs(n: Int): Int = if (n > 0) n else -n
println(abs(-39));

/**
  * while 求和
  * @param xs
  * @return
  */
 def sum(xs: List[Int]) = {
  var total = 0
  var index = 0
  while (index < xs.size) {
    total += xs(index)
    index += 1
  }
  total
}
println(sum(List(3, 4, -5, 54)));

四、使用递归对数列求和

/**
  * xs.head 返回列表里的头元素,即第一个元素
  * xs.tail 返回除头元素外的剩余元素组成的列表
  * 递归对函数求和
  * @param xs
  * @return
  */
def recursionSum(xs: List[Int]): Int =
  if (xs.isEmpty) 0 else xs.head + recursionSum(xs.tail)
println(recursionSum(List(3, 4, -5, 54)));

更为简便的方法

println(List(3, 4, -5, 54).foldLeft(0)((x0, x) => x0 + x))

该方法传入一个初始值 0,一个匿名函数,该匿名函数累加列表中的每一个元素,最终返回整个列表的和。使用上面的方法,我们甚至不需要定义额外的方法,就可以完成同样的操作。


五、模式匹配是Scala最广泛使用的功能之一,经过函数值和闭包。Scala中大力支持模式匹配处理消息。

 1. 模式匹配包括替代的序列,每个开始使用关键字case。每个备选中包括模式和一个或多个表达式,如果模式匹配将被计算。一个箭头符号=>分开的表达模式。

    

object Match extends App{
  def matchTest(x: Int): String = x match {
    case 1 => "one"
    case 2 => "two"
    case _ => "many"
  }
  println(matchTest(1))
  println(matchTest(2))
  println(matchTest(3))
  println(matchTest(4))

}

运行结果:

one
two
many
many

2. 使用case语句块定义一个函数,该函数映射整数字符串。匹配关键字提供应用函数(如模式匹配函数以上)为一个对象的一个方便的方法。

def matchTestAny(x: Any): Any = x match {
  case 1 => "one"
  case "two" => 2
  case y: Int => "scala.Int"
  case _ => "many"
}

println(matchTestAny(1))
println(matchTestAny("two"))
println(matchTestAny(3))
println(matchTestAny(4))
println(matchTestAny(List(1, 4, 5)))

运行结果:

one
2
scala.Int
scala.Int
many

3. 匹配使用case类

case classes是用于模式匹配与case 表达式指定类。这些都是标准类具有特殊修饰:case。

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)

运行结果:

Hi Alice!
Hi Bob!
Age: 32 year, name: Charlie?

    增加 case 关键字使编译器自动添加了许多实用的功能。关键字建议与模式匹配的情况下表达式的关联。

首先,编译器会自动转换的构造函数的参数为不可变的字段(vals)。val关键字是可选的。如果想可变字段,使用var关键字。因此,构造函数的参数列表现在更短。

    其次,编译器自动实现equals, hashCode, 和toString方法的类,它使用指定为构造函数参数的字段。因此,不再需要自己的toString方法。

    最后,还消失Person类的主体部分,因为没有需要定义的方法!

六、类是一个对象的蓝图。一旦定义一个类可以创建从类蓝图使用关键字new创建对象。

    Scala中类对象中不可有静态变量和静态方法,但是提供了“伴侣对象”的功能:在和类的同一个文件中定义同名的Object对象:(须在同一文件中;main方法定义在Object对象中)


/**
  * Created by Administrator on 2016/1/24.
  */
class Person(val namec: String,val agec:Int) {
  var name = namec
  var age = agec

  def run(dAge:Int)={
    println("name:"+name+"; age:"+(dAge+agec))
  }

}

可以扩展scala类以类似的方式,如在Java中的一样,但有两个限制:方法重载需要override关键字,只有主构造可以传递参数给基构造。

/**
  * Created by Administrator on 2016/1/24.
  */
class Boy(override val namec: String, override val agec:Int, val heightc:Int) extends Person(namec, agec){
  var height = heightc
  def run(dAge:Int,dHeight:Int)={
    println("name:"+namec+"; age:"+(dAge+agec)+"; height:"+(dHeight+heightc))
  }
}

extends子句有两种作用:它使类Location继承类Yiibai所有非私有成员,它使Location类作为Yiibai类的子类。 因此,这里的Yiibai类称为超类,而Location类被称为子类。扩展一个类,继承父类的所有功能,被称为继承,但scala允许继承,只能从一个唯一的类。

var boy = new Boy("jack", 12, 150);
boy.run(4, 12)
boy.run(34)

运行结果

name:jack; age:16; height:162
name:jack; age:46

单例对象

Scala比Java更面向对象,因为在Scala中不能有静态成员。相反,Scala有单例的对象。单例就是只能有一个实例,即,类的对象。可以使用关键字object代替class关键字,而不是创建单例。因为不能实例化一个单独的对象,不能将参数传递给主构造。前面已经看到全部采用单一对象,调用Scala的main方法的例子。

相关链接

http://www.yiibai.com/scala/scala_data_types.html

http://www.scala-lang.org/docu/files/ScalaTutorial.pdf?cm_mc_uid=58080025153914536211975&cm_mc_sid_50200000=1453627125




你可能感兴趣的:(Scala学习笔记(一))