Scala - Advanced

Method

Scala 的方法和 Java 可以看成是一样的,只是多了点语法糖。

使用 def 语句定义方法 Method 。

def addInt( a:Int, b:Int ) : Int = {
   var sum:Int = 0
   sum = a + b
   return sum
}

注:最后一行不用 return 也可以返回值

Unit

如果方法没有返回值,可以返回为 Unit ,这个类似于 Java 的 void ,如下:

def printMe( ) : Unit = {
   println("Hello, Scala!")
}

没有传参

如果没有传入参数,调用时的括号可以省略

// 花括号(有时)可以省略
// 返回值类型声明(有时)可以省略
def three() : = 1+2

println(three)

默认传参

可以为函数参数指定默认值,如果使用时没有传参,就用默认值。

def main(args: Array[String]) {
     println( "result : " + addInt() ); // 这里的括号不能省略
}

def addInt( a:Int=5, b:Int=7 ) : Int = {
   var sum:Int = 0
   sum = a + b
   return sum
}

命名传参

object Test {
   def main(args: Array[String]) {
        printInt(b=5, a=7);
   }
   def printInt( a:Int, b:Int ) = {
      println("Value of a : " + a );
      println("Value of b : " + b );
   }
}

可变参数

和Java类似,传入参数的个数可以变化,一个或者多个

def sum(numbers:Int*) = {
    var result = 0
    for(number <- numbers) {
      result += number
    }
    result
}

// 调用
println(sum(1,2))
println(sum(1,2,3))
println(sum(1,2,3,4))

Function

Scala 中的函数,和 Java 中的函数式编程 Lambda Expression 非常类似。

主要用来:

  1. 函数可以直接作为参数灵活地传递,到另一方法/函数中。进而实现 lazy 触发,这也是许多框架如Spark的核心思想之一。
  2. 函数可以方便地实现闭包 closure 。

使用 val 语句定义函数 Function 。

常用定义形式如下:

val fun1 = new Function2[Int,Int,Int]() {
  override def apply(v1: Int, v2: Int): Int = {
    v1+v2
  }
}

val fun2 = new ((Int, Int) => Int)() {
  override def apply(v1: Int, v2: Int): Int = {
    v1+v2
  }
}

// 最常用
val fun3 = (v1:Int,v2:Int) => v1+v2

// 空格 + 下划线 可以把 method 转换成 function
val fun4 = fun4Method _
def fun4Method(v1:Int,v2:Int): Int = {
  v1+v2
}

闭包

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

定义示例1:

var more = 1
val addMore = (x: Int) => x + more

scala> addMore(10)
res: Int = 11

(但是,上例从理解层面,不就相当于函数中引用了一个全局变量嘛,感受不出闭包的好处。)

实际示例2:

def makeIncreaser(more: Int) = (x: Int) => x + more

scala> val inc1 = makeIncreaser(1)
scala> val inc5 = makeIncreaser(5)

scala> inc1(10)
res: Int = 11

scala> inc5(10)
res: Int = 15

(从上例中,我们可以看到,闭包可以让我们更加灵活地定义函数,如inc1,inc5)

参考 -> scala 方法&函数 https://www.cnblogs.com/ulysses-you/p/7551188.html

构造器

主构造器 Constructor 和 附属构造器 Alternative Constructor

用途:对于一个类,我们可以有多个 Constructor ,其输入参数是不同的,这点和 Java 类似,但是语法有些区别。

// 主构造器
class Person(val name:String, val age:Int) {
  val school = "ustc"
  var gender:String = _

  // 附属构造器
  def this(name:String, age:Int, gender:String) {
    this(name, age) // 附属构造器的第一行代码必须要调用主构造器或者其他附属构造器
    this.gender = gender
  }
}

object ConstructorApp {
  def main(args: Array[String]): Unit = {
	// 使用 主构造器
    val person = new Person("zhangsan", 30)
    // 使用 附属构造器
	val person2 = new Person("PK", 18, "M")
  }
}

类 - basic

继承

class Person(val name:String, val age:Int) {
  val school = "ustc"
}

class Student(name:String, age:Int, var major:String) extends Person(name, age) {
}

val student = new Student("PK", 18, "Math")

重写

子类重写父类的方法或者变量时,必须使用 override 关键字!( 抽象 abstract 类型的除外)

class Person {
  var name = ""
}

class Employee extends Person {
  override var name = "zhangsan"
  var salary = 0.0
  override def toString = name + salary
}

抽象类

和 Java 类似,抽象类中可以有没有实现的方法或者没有赋值的参数。

实现类必须实现这些方法和参数。

类 - Object

object关键字,相当于 class 的单个实例,类似于 Java 中的 static ,通常在里面放一些静态的 field 和 method 。

实现 main 方法

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello World!!!")
  }
}

实现工具类

object继承抽象类,并重写抽象类中的方法

abstract class Hello(var message: String) {
  def sayHello(name: String): Unit
}

object HelloImpl extends Hello("hello") {
  override def sayHello(name: String) = {
    println(message + ", " + name)
  }
}

//调用
HelloImpl.sayHello("Tom")

作为伴生对象

object Person {
  private val eyeNum = 2
  def getEyeNum = eyeNum
}

class Person(val name: String, val age: Int) {
  def sayHello = println("Hi, " + name 
      + ", I guess you are " + age + " years old!" 
      + ", and usually you must have " + Person.eyeNum + " eyes.")
}

val person = new Person("Tom",23)
person.sayHello

实现特殊的 apply 方法

让对象创建更加简洁

// 示例1

class Person(val name: String)

object Person {
  def apply(name: String) = new Person(name)
}

val person = Person("Tom")

// 示例2

class Person()

object Person {
  def apply() = new Person()
}

val person = Person

注:apply 方法在 object 和 class 中都可以定义。那使用时具体是调用了那个呢?规则如下:

类名() ==> Object.apply
对象() ==> Class.apply

实现枚举值

// 示例1

object Season extends Enumeration {
  val SPRING, SUMMER, AUTUMN, WINTER = Value
}

Season(0)

// 示例2

object Season extends Enumeration {
  val SPRING = Value(0, "spring")
  val SUMMER = Value(1, "summer")
  val AUTUMN = Value(2, "autumn")
  val WINTER = Value(3, "winter")
}

Season.withName("spring")

参考 -> scala之object类 https://blog.csdn.net/weixin_39966065/article/details/90232640

Trait

Scala Trait 特征 相当于 Java 的 Interface 接口(加强版),它还可以定义属性和方法的实现。

trait Equal {
  def isEqual(x: Any): Boolean
  def isNotEqual(x: Any): Boolean = !isEqual(x)
}

实现 Trait 使用 extends 关键字,如果有多个使用 with 关键字连接。

class Person(name: String) extends Equal with Logger {

}

Case

模式匹配

def matchTest(x: Int): String = x match {
  case 1 => "one"
  case 2 => "two"
  case _ => "many"
}

Exception

异常处理

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException

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")
         }
      } finally {
         println("Exiting finally...")
      }
   }
}

I/O

读:从屏幕上读取用户输入

import scala.io._
object Test {
   def main(args: Array[String]) {
      print("Please input: " )
      val line = StdIn.readLine()
      println("Your input is: " + line)
   }
}

读:从文件上读取内容

import scala.io.Source

object Test {
   def main(args: Array[String]) {
      println("file content is: " )
      Source.fromFile("test.txt" ).foreach{
         print
      }
   }
}

写:写入文件

import java.io._

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

参考

Fork me on GitHub