Scala Learn 03 File/Match/Trait

Chap 9 文件/正則表達式

focus onjava

  1. Source.fromFile(..).getLines.toArray 輸出文件的全部行正則表達式

  2. Source.fromFile(..).mkString 以字符串形式輸出文件內容數組

  3. 將字符串轉換爲數字, 能夠用 toInt 或 toDouble 方法app

  4. 使用 Java 的 PrintWriter 來寫入文本文件ide

  5. "正則".r 是一個 Regex 對象spa

  6. 正則表達式 包含 或者 「 , 使用 """..."""scala

  7. 若是正則模式包含分組, 你能夠用以下語法來提取它們的內容 for (regex(變量1, ...) <- 字符串)rest

9.1 Read Line、Character

import java.io.PrintWriter
import java.io.File
import scala.io.Source

object HelloFile extends App {

  val writer = new PrintWriter(new File("test.txt")) // base dir will generate test.txt

  writer.write("Hello Scala In test.txt")

  writer.close()

  // 9.0 console read
  print("Please enter your input : ")

  val line = Console.readLine

  println("Thanks, you just typed: " + line)

  // 9.1 Read File content
  println("Following is the content read:")

  Source.fromFile("test.txt").foreach {
    print
  }

  // mkString / Array
  val source = Source.fromFile("test.txt")

  val contents = source.mkString
//
//  val arr = source.getLines().toArray
//
  println("\n\ncontents : " + contents + "\n")
//
//  println("\n\narr : " + arr)
  source.close()

  // 9.2 讀取字符

  val source2 = Source.fromFile("test.txt")

  val iterator = source2.buffered

  while (iterator.hasNext) {
    if (iterator.head != 'e') {
      print(iterator.next())
    } else {
      iterator.next()
    }
  }

  source2.close()

}

9.2 Read Word/Number/URL

object ReadLine extends App {

  val source = Source.fromFile("num.txt", "UTF-8")

  // 9.3 讀取詞法單元 和 數字
  val tokens = source.mkString.split("\\s+")

  val numbers = tokens.map(_.toDouble)

  for (w <- numbers) {
    println(w)
  }

  /* Output
  12.0
  34.0
  56.0
  78.0
  89.0
    */

  source.close()

  println("haow old are you ?")
  val age = readInt()
  println("age : " + age)

  // 9.4 從 URL 或 其餘源 讀取
  val source1 = Source.fromURL("http://52binge.com", "UTF-8") // URL 須要事先 知道字符集
  val source2 = Source.fromString("Hello,World")
  val source3 = Source.stdin

}

9.3 BinaryFile/PrintWrite

object BinaryFileAndPrintWriteFile extends App {

  // 9.5 讀取二進制文件 (使用Java類庫)

  val file = new File("num.txt")

  val in = new FileInputStream(file)

  val bytes = new Array[Byte](file.length().toInt) // File readTo 字符數組

  in.read(bytes)

  for (c <- bytes) {
    println(c.toChar)
  }

  in.close()

  // 9.6 寫入文本文件

  val out = new PrintWriter("numbers.txt")
  for (i <- 1 to 10) {
    out.println(i)
  }
  out.close()

}

9.4 Serialize Object

object DirSerialize {

  // 9.7 訪問目錄, (Scala不是很是方便)

  // 9.8 序列化

  // 1. Java  序列化, public class Person implements java.io.Serializable
  // 2. Scala 序列化, @SerialVersionUID(42L) class Person extends Serializable

  /*

  val fred = new Person(...)
  import java.io._
  val out = new ObjectOutputStream(new FileOutputStream("/tmp/test.obj"))
  out.writeObject(fred)
  out.close()

  val in = new ObjectInputStream(new FileOInputStream("/tmp/test.obj"))
  val savedFred = in.readObject().asInstanceOf[person]
   */
 // Scala 集合類都是可序列化的, 所以 你能夠把它們用作你的可序列化類的成員
  /*

  class Person extends Serializable {
    private val friends = new ArrayBuffer[Person] // ok--ArrayBuffer 是可序列化的

   */
}

9.5 Match 正則

object Match extends App {
  val numPattern = "[0-9]".r
  val wsnumwsPattern = """\s+[0-9]+\s""".r

  for (matchString <- numPattern.findAllIn("99 bottles, 98 bottles")) {
    println(matchString)
  }

  for (matchString <- wsnumwsPattern.findAllIn("99 bottles, 998 9bottles")) {
    println("B" + matchString + "B")
  }

  // 9.10 正則 表達式 組
  val numitemPattern = "([0-9]+) ([a-z]+)".r
  val numitemPattern(num, item) = "99 bottles"
  for (numitemPattern(num, item) <- numitemPattern.findAllIn("99 bottles, 998 9bottles")) {
    println(num + " " + item)
  }

}

MyGithub日誌

Chap 10 Trait

focus oncode

  1. Class 能夠實現任意數量的 Trait

  2. Trait 能夠要求實現它們的 Class 具有特定的 字段、方法、超類

  3. Scala Trait 可提供 方法字段 的實現

  4. 多個 Trait 疊加, 順序很重要。 方法 先被執行的 Trait 排在更後面

Scala 提供 「Trait」 而非 Interface。Trait 可同時提供 抽象方法具體方法, 而 Class 能夠實現多個 Trait

10.1 當作接口使用的 Trait

trait Logger {
  def log(msg: String) // 這是個抽象方法, 你不須要聲明爲 abstract, 特質中未被實現的方法就是 抽象方法
}

/**
  * Date : 2016-04-07
  * 全部的 Java 接口 均可以 做爲 Scala trait 使用
  */
class ConsoleLogger extends Logger with Cloneable with Serializable {
  // use extends
  def log(msg: String): Unit = { // 重寫 Trait 的 抽象方法 不須要給出 override 關鍵字
    println(msg)
  }
  // 和 Java 同樣, Scala 類 只能有一個 超類, 但 能夠有 任意數量的 Trait

}

10.2 帶有具體實現的 Trait

trait Logged {
  def log(msg: String) {}
}

trait ConsolePrintLogger extends Logged {
  override def log(msg: String): Unit = {
    println(msg)
  }
}
class SavingsAccount extends Account with ConsolePrintLogger {
  def withdraw(amount: Double): Unit = {
    if (amount > balance) {
      log("Insufficient funds")
    } else {
      balance -= amount
    }
  }
  // 注 : 讓 Trait 存在具體行爲存在一個 弊端. 當 Trait 改變時, 全部混入了該 Trait 的 Class 都必須 re compile
}

10.3 帶有 Trait 的對象

class SavingsAcc extends Account with Logged {
  def withdraw(amount: Double): Unit = {
    if (amount > balance) {
      log("Insufficient funds")
    } else {
      balance -= amount
    }
  }
}
// 看上去,毫無心義, 其實否則,你能夠在 構造對象 的時候 "混入" 一個更好的 日誌 記錄器

object SavingsAcc extends App {
  val acct1 = new SavingsAcc with ConsolePrintLogger
//  val acct2 = new SavingsAcc with FileLogger
  acct1.withdraw(100)
}

10.4 疊加在一塊兒的 Trait

你能夠爲 Class 或 Object 添加多個互相調用的特質。

trait TimestampLogger extends Logged {
  override def log(msg: String) {
    super.log(new java.util.Date() + " " + msg)
  }
}
trait ShortLogger extends Logged {
  val maxLength = 15 // 關於 Trait 的 Field
  override def log(msg: String) {
    super.log(if (msg.length <= maxLength) msg else msg.substring(0, maxLength - 3) + "...")
  }
}

上述 log 方法 每個都將修改過的消息傳遞給 super.log

對 Trait 而言, super.log 並不像 Class 那樣擁有相同的含義。
實際上, super.log 調用的是 Trait層級 中的下一個 Trait,具體是哪個具體 Trait 的順序決定

val acct1 = new SavingsAccount with ConsolePrintLogger with TimestampLogger with ShortLogger

output :

Sun Feb 06 17:45:45 ICT 2011 Insufficient...

10.5 在特質中重寫抽象方法

trait Logger {
  def log(msg: String)  // 這是個抽象方法
}
trait TimestampLogger extends Logged {
  override def log(msg: String) {
    super.log(new java.util.Date() + " " + msg)
  }
}

編譯器將 super.log 調用標記爲 錯誤。Logger.log 方法沒有實現。咱們無法知道哪一個 log 方法會被調用

Scala 認爲 TimestampLogger 依然是 抽象 的, 由於你必須給 方法 打上 abstract override

trait TimestampLogger extends Logged {
  abstract override def log(msg: String) {
    super.log(new java.util.Date() + " " + msg)
  }
}

10.6 當作富接口使用的Trait

trait Logger {
  def log(msg: String)
  def info(msg: String) { log("INFO: " + msg) }
  def warn(msg: String) { log("WARN: " + msg) }
  def severe(msg: String) { log("SEVERE: " + msg) }

使用 Logger 的 Class 就能夠任意 調用這些 log 方法了。

class SavingsAccount extends Account with Logged {
  def withdraw(amount: Double): Unit = {
    if (amount > balance) {
      severe("Insufficient funds")
    } else {
      balance -= amount
    }
  }
  ...
  override def log(msg: String) { println(msg); }
}

Scala 這種 Trait 使用 具體 和 抽象 方法隨處可見

10.7 Trait 中的具體 Field

Trait 中的 Field 能夠是具體的,也能夠是抽象的。

trait ShortLogger extends Logged {
  val maxLength = 15 // 具體的字段
  ...
}
class SavingsAccount extends Account with ConsolePrintLogger with ShortLogger {
  var interest = 0.0
  def withdraw(amount: Double): Unit = {
    if (amount > balance) {
      log("Insufficient funds")
    } else {
      balance -= amount
    }
  }
}

你能夠把具體的特質字段當作是針對使用該特質的類的 「裝配指令」。任何混入的字段都自動成爲該類 本身 的 字段

圖片描述

10.8 Trait 中的抽象字段

Trait 中未被初始化的字段,在具體的子類中 必須被 override (不須要寫該關鍵字)

trait ShortLogger extends Logged {
  val maxLength: Int // 抽象字段
  override def log(msg: String) {
    super.log(
      if (msg.length <= maxLength) msg
      else msg.substring(0, maxLength - 3 ) + "..."
    ) // 實現中使用了 maxLength
  }
  ...
}

在 一個 具體的 Class 使用該 Trait 中,你必須提供 maxLength 字段

class SavingsAccount extends Account with ConsoleLogger with ShortLogger {
  val maxLength = 20  // 不須要寫 override
  ...
}

10.9 Trait 構造順序

trait FileLogger extends Logger {
  val out = new PrintWrite("app.log")     // 這是 特質構造器的一部分
  out.println("# " + new Date().toString) // 一樣是特質構造器的一部分

  def log(msg: String) {
    out.println(msg)
    out.flush()
  }
}

構造順序

class SavingsAccount extends Account with FileLogger with ShortLogger

  1. Account (超類)

  2. Logger (第一個 Trait 的 父 Trait)

  3. FileLogger (第一個 Trait)

  4. ShortLogger (第二個 Trait)。 注意 它的 父trait Logger 已被構造

  5. SavingsAccount (Class)

說明 : 構造器的順序是 類 的 線性化 的反向

10.10 初始化 Trait 中的字段

Trait 不能有構造器參數. 每一個 Trait 都有一個無參數的構造器

說明 : 缺乏構造器參數是 Trait 與 Class 的惟一技術差異

這個侷限對於那些須要某種定製纔有用的 Trait 來講會是一個問題

10.11 擴展 Class 的 Trait

trait 能夠擴展另外一個 trait, 而由 trait 組成的繼承層級也很常見。而由 trait 擴展 class, 這個 class 會自動成爲全部混入該 trait 的 超類

相關文章
相關標籤/搜索