【发布时间】:2015-06-03 23:00:45
【问题描述】:
我每天都在 Scala 中学习新事物。我目前采取的路线是从 java nio 中提取功能并从中实现 Scala 实现。我观察到其他 Scala 专家如何使用 java.nio.files 包和 FileVisitor 接口递归地遍历具有子目录和文件的嵌套目录结构。
但是,我遇到了一个小问题。我不太明白
我注意到 paulp 维护的 github 上的一个实现,我无法理解。我将在这里展示他的代码,以及我的问题和疑虑:
import java.nio.file.{ FileVisitResult, SimpleFileVisitor }
trait PathVisitor extends FileVisitor[Path] {
def preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult
def postVisitDirectory(dir: Path, exc: IOException): FileVisitResult
def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult
def visitFileFailed(file: Path, exc: IOException): FileVisitResult
}
好的,他从 FileVisitor 扩展而来,这是一个 Java 接口:起初,我不确定 Scala trait 是否可以从 java 接口扩展。我在 REPL 中对此进行了测试。显然这没关系。 REPL 输出如下:
C:\Users\lulu\Documents\GitHub\akkaexperiments>scala 欢迎使用 Scala 版本 2.10.2(Java HotSpot(TM) 64 位服务器 VM,Java 1.7.0_71)。 输入表达式以对其进行评估。 输入 :help 了解更多信息。
scala> 导入 java.nio.file.{ FileVisitor }; 导入 java.nio.file.FileVisitor
scala> 导入 java.nio.file.Path 导入 java.nio.file.Path
scala> trait PathVisitor 扩展 FileVisitor[Path] 定义特征 PathVisitor
斯卡拉>
除此之外,我现在查看了 FileVisitor.java 的源代码。它在下面: 这就是 paulp 有趣的地方。下面的代码后面是解释。
public interface FileVisitor<T> {
FileVisitResult preVisitDirectory(T dir);
FileVisitResult preVisitDirectoryFailed(T dir, IOException exc);
FileVisitResult visitFile(T file, BasicFileAttributes attrs);
FileVisitResult visitFileFailed(T file, IOException exc);
FileVisitResult postVisitDirectory(T dir, IOException exc);
}
---------------------
paulp's code continues below:
object PathVisitor {
class Simple extends SimpleFileVisitor[Path] with PathVisitor { }
val Continue = FileVisitResult.CONTINUE
val SkipSiblings = FileVisitResult.SKIP_SIBLINGS
val SkipSubtree = FileVisitResult.SKIP_SUBTREE
val Terminate = FileVisitResult.TERMINATE
def apply(f: (Path, BasicFileAttributes) => FileVisitResult): PathVisitor = new Simple {
override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = f(file, attrs)
}
}
------
For context and comparison purposes here is the code for SimpleFileVisitor:
public class SimpleFileVisitor<T> implements FileVisitor<T> {
protected SimpleFileVisitor() {
}
@Override
public FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)
throws IOException
{
Objects.requireNonNull(dir);
Objects.requireNonNull(attrs);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(T file, BasicFileAttributes attrs)
throws IOException
{
Objects.requireNonNull(file);
Objects.requireNonNull(attrs);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(T file, IOException exc)
throws IOException
{
Objects.requireNonNull(file);
throw exc;
}
@Override
public FileVisitResult postVisitDirectory(T dir, IOException exc)
throws IOException
{
Objects.requireNonNull(dir);
if (exc != null)
throw exc;
return FileVisitResult.CONTINUE;
}
}
在这一切之后,我提出以下意见: 类 Simple 扩展了 SimpleFileVisitor,它是 Java FileVisitor 接口的一个实现
paulp 还混合了 trait PathVisitor,其方法定义与 Java FileVisitor 接口中的方法定义完全相同。
这里让我感到困惑的是: 1)为什么他在扩展 SimpleFileVisitor 的同时还混合了 PathVisitor 特征? 2) 当它们是相同的方法时,我们不是试图要求 Simple 类同时尊重 SimpleVisitor 契约和 FileVisitor trait 未实现的方法吗? 3)他包装了Simple Class,一堆vals来表示SimpleFileVisitor方法的返回类型和一个apply方法。好的,那么您认为这种结构背后的想法是什么?
我真的很想使用 PaulP 制定的结构,但这令人费解。它可能需要一些清理。 请指教。
【问题讨论】:
-
保罗这样做是“正确的方式”,我希望我有时间解释原因。 (正确的方法不止一种,但这是其中之一。)我希望其他人会这样做!关键是要考虑这些东西对你的面向 Scala 的 API 有什么作用。如果你自己想通了,请写一个答案!
-
感谢您的洞察力。我一定会报告我的发现。这是一个令人兴奋的搜索
-
我应该说--我假设这是正确的方法,因为它适合我没有的更大的图片。