控制抽象
减少重复代码
重复代码
这是一开始最可能写出来的代码,代码很简单,就是文件名的过滤功能。
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()
}
}
}