scala學習:控制抽象

控制抽象

減小重複代碼

重複代碼

這是一開始最可能寫出來的代碼,代碼很簡單,就是文件名的過濾功能。函數

object FileMatcher {

  private def files = new File(".").listFiles()

  def filesEnding(query: String): Array[File] = {

    for (file <- files; if file.getName.endsWith(query))
      yield file
  }

  def FilesContaining(query: String): Array[File] = {
    for (file <- files; if file.getName.contains(query))
      yield file
  }

  def FilesRegexing(query:String): Unit ={
    for (file <- files; if file.getName.matches(query))
      yield file
  }
}

將邏輯抽象出來

定義個filesMatching方法,將邏輯抽象,如今看着就舒服多了。code

但還不夠完美。資源

object FileMatcher {

  private def files = new File(".").listFiles()

  def filesEnding(query: String): Array[File] = {

    filesMatching(query,_.endsWith(_))
  }

  def FilesContaining(query: String): Array[File] = {
    filesMatching(query,_.contains(_))
  }

  def FilesRegexing(query: String): Unit = {
    filesMatching(query,_.matches(_))
  }
  
  def filesMatching(query: String, matcher: (String, String) => Boolean): Array[File] = {

    for (file <- files; if matcher(file.getName, query))
      yield file
  }
}

去掉沒必要要參數

在邏輯方法中,去掉參數,這樣就更清爽了。get

object FileMatcher {

  private def files = new File(".").listFiles()

  def filesEnding(query: String): Array[File] = {

    filesMatching(_.endsWith(query))
  }

  def FilesContaining(query: String): Array[File] = {
    filesMatching(_.contains(query))
  }

  def FilesRegexing(query: String): Unit = {
    filesMatching(_.matches(query))
  }

  def filesMatching(matcher: String => Boolean): Array[File] = {

    for (file <- files; if matcher(file.getName))
      yield file
  }
}

借貸模式

假設你須要打開一個文件,你最後老是須要考慮關閉資源。有沒有什麼辦法,讓咱們不會忽略這個動做。(不使用try())it

object printWriterTest {

  def withPrintWriter(file: File)(op: PrintWriter => Unit): Unit = {
    val writer = new PrintWriter(file)
    try {
      op(writer)
    } finally {
      writer.close()
    }
  }
}

接下來你能夠這麼使用這個函數io

withPrintWriter(new File("test.txt"))(writer => writer.println("test"))

傳名參數

傳名參數比起簡單的參數傳輸,不同的地方在於。test

簡單的參數傳輸會先計算這個表達式,而傳名參數則在須要它的時候纔會去計算。object

如下示例代碼,只有boolAssert(5/0==0) 纔會拋出錯誤。file

object ByNameAssertTest {

  def main(args: Array[String]): Unit = {
    byNameAssert(5 / 0 == 0)
    boolAssert(5 / 0 == 0)
  }

  var assertEnable = false


  def byNameAssert(predict: => Boolean): Unit = {

    if (assertEnable && !predict) {
      throw new AssertionError()
    }
  }

  def boolAssert(predict: Boolean): Unit = {
    if (assertEnable && !predict) {
      throw new AssertionError()
    }
  }

}
相關文章
相關標籤/搜索