我每天都在Scala学习新东西。我目前采用的方法是从java中提取功能,并将Scala实现从它们中提取出来。我已经观察到其他Scala专家如何使用java.nio.files包,以及FileVisitor接口递归地遍历带有子目录和文件的嵌套目录结构。
但是,我遇到了一个小问题。我不太明白
我注意到由paulp维护的github上的一个实现,我不能使用understand.It作为他的代码,我将在这里展示我的问题和关注:
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特性是否可以从java接口扩展。我在REPL中测试了这个。很明显这没问题。REPL的产出如下:
C:\Users\lulu\Documents\GitHub\akkaexperiments>scala欢迎使用ScalaVersion2.10.2 (Java (TM)64位服务器VM,Java1.7.0_71).键入要对它们进行计算的表达式。类型:帮助获取更多信息。
scala>导入java.nio.file.{ FileVisitor };导入java.nio.file.FileVisitor
scala>导入java.nio.file.Path导入java.nio.file.Path
scala>属性PathVisitor扩展了FileVisitorPath定义的特征PathVisitor
scala>
在此之后,我看了一下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,它是FileVisitor接口的实现
另外,特征PathVisitor中的paulp混合,其方法定义与接口中的方法定义完全相同。
让我感到困惑的是: 1)为什么他同时扩展了SimpleFileVisitor,同时也混合了PathVisitor特性? 2)我们是不是想让类简单地遵守SimpleVisitor契约和FileVisitor特性未实现的方法,当它们是相同的方法时? 3)他封装了简单类、一堆表示SimpleFileVisitor方法的返回类型的值和一个应用方法。好吧,你认为这种结构背后的想法是什么?
我真的很想使用PaulP布局的结构,但这是令人费解的。可能需要清理一下。请给我建议。
发布于 2015-04-02 02:17:54
这样做的原因是为了提供无缝的Scala体验。首先,第一个特征是指定路径,而不是抽象出您可能需要访问的任何T。如果你真的只对路径感兴趣,不用担心泛型是件好事。
然后,他以Scala样式为您提供常量,这样您就不必从Java获取它们。
他给出了一个路径特定的SimpleFileVisitor,而不需要额外的工作,只需混合PathVisitor特性即可。
现在,问题仍然是:为什么这样做而不是仅仅说
type PathVisitor = java.nio.file.FileVisitor有两个原因。首先,类型别名并不是真正的一流语言结构,所以您将倾向于看到Java类型而不是Scala类型(稍微不太好)。另外,如果您以这种方式设置它,那么以后可以更容易地将功能添加到框架中。如果您确信您不想添加任何内容,那么这样做的理由就更少了。
现在,关于具体问题:
SimpleFileVisitor获得实现,但是让它获得Scala的特性。apply-style构建器而不是new也是如此。https://stackoverflow.com/questions/29354517
复制相似问题