scala简介

时间: | 分类: scala

菜鸟教程Scala学习笔记

基本语法:

  • 区分大小写
  • 类名 class 第一个字母要大写 class MyFirstScalaClass
  • 方法名 def 第一个字母用小写 def myMethodName()
  • 程序文件名应与对象名称完全匹配
  • def main(args: Array[String]) - Scala程序从main()方法开始处理,这是每一个Scala程序的强制程序入口部分

换行符:

  • 面向行的语言,可以用;结束,也可以不写,但是一行中有多个语句是要用分号分隔的

引用:

  • import 语句可以出现在任何地方,而不只是文件顶部
  • 想要引入包中的几个成员,可以使用selector

Scala变量

  • 变量声明:

    var myVar : String = "Foo"
  • 常量声明:

    val myVal : String = "Foo"
  • 变量类型引用:在 Scala 中声明变量和常量不一定要指明数据类型,在没有指明数据类型的情况下,其数据类型是通过变量或常量的初始值推断出来的。所以,如果在没有指明数据类型的情况下声明变量或常量必须要给出其初始值,否则将会报错。
  • scala支持声明多个变量

Scala 访问修饰符

  • Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。
  • 私有(private)成员:用 private 关键字修饰,带有此标记的成员仅在包含了成员定义的类或对象内部可见,同样的规则还适用内部类。

    class Outer{
     class Inner{
     private def f(){println("f")}
     class InnerMost{
         f() // 正确
         }
     }
     (new Inner).f() //错误
    }
  • 保护(protected)成员:在 scala 中,对保护(Protected)成员的访问比 java 更严格一些。因为它只允许保护成员在定义了该成员的的类的子类中被访问。而在java中,用protected关键字修饰的成员,除了定义了该成员的类的子类可以访问,同一个包里的其他类也可以进行访问。

    package p{
    class Super{
     protected def f() {println("f")}
     }
     class Sub extends Super{
         f()
     }
     class Other{
         (new Super).f() //错误
     }
    }
  • 作用域保护(待学习。。。

Scala方法与函数

  • Scala 方法是类的一部分 ,而函数是一个对象可以赋值给一个变量 。Scala 中使用 val 语句可以定义函数,def 语句定义方法。

     class Test{
       def m(x: Int) = x + 3
       val f = (x: Int) => x + 3
     }
    • 如果你不写等于号和方法主体,那么方法会被隐式声明为抽象(abstract),包含它的类型于是也是一个抽象类型。

      def functionName ([参数列表]) : [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 printMe( ) : Unit = {
     println("Hello, Scala!")
       }
    }
  • 函数可作为一个参数传入到方法中,而方法不行。

    object MethodAndFunctionDemo {
      //定义一个方法
      //方法m2参数要求是一个函数,函数的参数必须是两个Int类型
      //返回值类型也是Int类型
      def m1(f:(Int,Int) => Int) : Int = {
        f(2,6)
      }
    
      //定义一个函数f1,参数是两个Int类型,返回值是一个Int类型
      val f1 = (x:Int,y:Int) => x + y
      //再定义一个函数f2
      val f2 = (m:Int,n:Int) => m * n
    
      //main方法
      def main(args: Array[String]): Unit = {
        //调用m1方法,并传入f1函数
        val r1 = m1(f1)
    
        println(r1)
    
        //调用m1方法,并传入f2函数
        val r2 = m1(f2)
        println(r2)
      }
    }
  • 在Scala中无法直接操作方法,如果要操作方法,必须先将其转换成函数。有两种方法可以将方法转换成函数:

    `val f1 = m _` 在方法名称m后面紧跟一个空格和下划线告诉编译器将方法m转换成函数,而不是要调用这个方法。 也可以显示地告诉编译器需要将方法转换成函数: `val f1: (Int) => Int = m`
    
  • 函数必须要有参数列表,而方法可以没有参数列表

Scala 闭包

  • 闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
  • 闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。
  • 函数体内有一个变量 i,它作为函数的一个参数。如下面的另一段代码: val multiplier = (i:Int) => i * factor 在 multiplier 中有两个变量:i 和 factor。其中的一个 i 是函数的形式参数,在 multiplier 函数被调用时,i 被赋予一个新的值。然而,factor不是形式参数,而是自由变量,考虑下面代码:

     var factor = 3  
     val multiplier = (i:Int) => i * factor  
    • 这里我们引入一个自由变量 factor,这个变量定义在函数外面。

    这样定义的函数变量 multiplier 成为一个"闭包",因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。

Scala 字符串

  • 我们前面提到过 String 对象是不可变的,如果你需要创建一个可以修改的字符串,可以使用 String Builder 类
object Test {
   def main(args: Array[String]) {
      val buf = new StringBuilder;
      buf += 'a'
      buf ++= "bcdef"
      println( "buf is : " + buf.toString );
   }
}
  • 字符串连接:string1.concat(string2);

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

Scala 数组

  • 声明数组:

    var z:Array[String] = new Array[String](3)
    
    或
    
    var z = new Array[String](3)
    或
    var z = Array("Runoob", "Baidu", "Google")
  • 多维数组:

    import Array._
    
    object Test {
       def main(args: Array[String]) {
          var myMatrix = ofDim[Int](3,3)
          
          // 创建矩阵
          for (i <- 0 to 2) {
             for ( j <- 0 to 2) {
                myMatrix(i)(j) = j;
             }
          }
          
          // 打印二维阵列
          for (i <- 0 to 2) {
             for ( j <- 0 to 2) {
                print(" " + myMatrix(i)(j));
             }
             println();
          }
        
       }
    }

Scala类和对象

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

  • Scala继承:

    • 重写一个非抽象方法必须用override修饰符
    • 只有主构造函数才可以往基类的构造函数里写参数
    • 子类中重写超类的抽象方法时,不需要override关键字
    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);
       }
    }
    
    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);
       }
    }

实例中 Location 类继承了 Point 类。Point 称为父类(基类),Location 称为子类。override val xc 为重写了父类的字段。

  • 在Scala中,没有static,用关键字object关键字。Scala中使用单例模式时,出了自定义的类之外,还要顶一个一个同名的object对象,且不能带参数

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

    单例对象的实现

    import java.io._
    
    class Point(val xc: Int, val yc: Int) {
       var x: Int = xc
       var y: Int = yc
       def move(dx: Int, dy: Int) {
          x = x + dx
          y = y + dy
       }
    }
    
    object Test {
       def main(args: Array[String]) {
          val point = new Point(10, 20)
          printPoint
    
          def printPoint{
             println ("x 的坐标点 : " + point.x);
             println ("y 的坐标点 : " + point.y);
          }
       }
    }
**伴生对象的实现**
/* 文件名:Marker.scala
 * author:菜鸟教程
 * url:www.runoob.com
 */

// 私有构造方法
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")  
    }
}

Scala Trait

一般情况下Scala的类只能够继承单一父类,但是如果是Trait的话就可以继承多个,实现了多重继承


Scala Scala入门



失学失业还秃头


文章归档