focus onjava
Source.fromFile(..).getLines.toArray 輸出文件的全部行正則表達式
Source.fromFile(..).mkString 以字符串形式輸出文件內容數組
將字符串轉換爲數字, 能夠用 toInt 或 toDouble 方法app
使用 Java 的 PrintWriter 來寫入文本文件ide
"正則".r 是一個 Regex 對象spa
正則表達式 包含 或者 「 , 使用 """..."""scala
若是正則模式包含分組, 你能夠用以下語法來提取它們的內容 for (regex(變量1, ...) <- 字符串)rest
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() }
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 }
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() }
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 是可序列化的 */ }
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日誌
focus oncode
Class 能夠實現任意數量的 Trait
Trait 能夠要求實現它們的 Class 具有特定的 字段、方法、超類
Scala Trait 可提供 方法 和 字段 的實現
多個 Trait 疊加, 順序很重要。 方法 先被執行的 Trait 排在更後面
Scala 提供 「Trait」 而非 Interface。Trait 可同時提供 抽象方法 和 具體方法, 而 Class 能夠實現多個 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 }
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 }
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) }
你能夠爲 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...
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) } }
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 使用 具體 和 抽象 方法隨處可見
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 } } }
你能夠把具體的特質字段當作是針對使用該特質的類的 「裝配指令」。任何混入的字段都自動成爲該類 本身 的 字段
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 ... }
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
Account (超類)
Logger (第一個 Trait 的 父 Trait)
FileLogger (第一個 Trait)
ShortLogger (第二個 Trait)。 注意 它的 父trait Logger 已被構造
SavingsAccount (Class)
說明 : 構造器的順序是 類 的 線性化 的反向
Trait 不能有構造器參數. 每一個 Trait 都有一個無參數的構造器
說明 : 缺乏構造器參數是 Trait 與 Class 的惟一技術差異
這個侷限對於那些須要某種定製纔有用的 Trait 來講會是一個問題
trait 能夠擴展另外一個 trait, 而由 trait 組成的繼承層級也很常見。而由 trait 擴展 class, 這個 class 會自動成爲全部混入該 trait 的 超類