乐趣区

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 方法,将逻辑抽象,现在看着就舒服多了。

但还不够完美。

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

去掉不必要参数

在逻辑方法中,去掉参数,这样就更清爽了。

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

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

接下来你可以这么使用这个函数

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

传名参数

传名参数比起简单的参数传输,不一样的地方在于。

简单的参数传输会先计算这个表达式,而传名参数则在需要它的时候才会去计算。

以下示例代码,只有 boolAssert(5/0==0) 才会抛出错误。

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

}
退出移动版