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 的 超类

相关文章
相关标签/搜索