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()
    }
  }

}
相关文章
相关标签/搜索