简体   繁体   English

Scala:特征扩展了java.nio.file.FileVisitor

[英]Scala: trait extends java.nio.file.FileVisitor

I learn new things in Scala everyday. 我每天都会在Scala中学习新事物。 The current route I am taking is to pull out functionality from java nio and make Scala implementations out of them. 我目前采用的方法是从java nio中提取功能,并从中实现Scala实现。 I have observed how other Scala experts are using the java.nio.files package, and the FileVisitor interface to recursively walk down a nested directory structure with sub-directories and files. 我已经观察到其他Scala专家如何使用java.nio.files包和FileVisitor接口来递归地浏览带有子目录和文件的嵌套目录结构。

But, I have run into a slight problem. 但是,我遇到了一个小问题。 I cannot quite make sense of 我不太明白

I noticed an implementation on github maintained by paulp, that I cannot understand.It is his code that I will present here, with my questions and concerns: 我注意到由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
     }

Okay, he extends from FileVisitor, which is a Java interface: At first, I was not sure if a Scala trait can extend from a java interface. 好的,他是从FileVisitor扩展而来的,FileVisitor是一个Java接口:首先,我不确定Scala特性是否可以从Java接口扩展。 I tested this out in the REPL. 我在REPL中对此进行了测试。 Apparently this is Okay. 显然这没关系。 REPL output is below: REPL输出如下:

C:\\Users\\lulu\\Documents\\GitHub\\akkaexperiments>scala Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_71). C:\\ Users \\ lulu \\ Documents \\ GitHub \\ akkaexperiments> scala欢迎使用Scala 2.10.2版(Java HotSpot™64位服务器VM,Java 1.7.0_71)。 Type in expressions to have them evaluated. 输入表达式以对其求值。 Type :help for more information. 输入:help以获得更多信息。

scala> import java.nio.file.{ FileVisitor }; scala> import java.nio.file。{FileVisitor}; import java.nio.file.FileVisitor 导入java.nio.file.FileVisitor

scala> import java.nio.file.Path import java.nio.file.Path scala>导入java.nio.file.Path导入java.nio.file.Path

scala> trait PathVisitor extends FileVisitor[Path] defined trait PathVisitor scala>特征PathVisitor扩展FileVisitor [Path]定义的特征PathVisitor

scala> 斯卡拉>


With that out of the way, I now looked at the source for FileVisitor.java. 有了这些,我现在看了FileVisitor.java的源代码。 Here it is below: This is where paulp is intriguing. 这是下面的内容:这是paulp吸引人的地方。 Explanation follows after the below code. 以下代码后面有解释。

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

}

After all this, I make the following observations: class Simple extends SimpleFileVisitor, which is an implementation of the Java FileVisitor interface 完成所有这些之后,我将进行以下观察:类Simple扩展了SimpleFileVisitor,它是Java FileVisitor接口的实现。

Also paulp mixes in trait PathVisitor, whose method definitions are exactly the same as the ones in the Java FileVisitor interface. 还要在特征PathVisitor中混合使用paulp,该特征的方法定义与Java FileVisitor接口中的方法定义完全相同。

What is the baffling to me here is: 1) why did he extend SimpleFileVisitor at the same time as he also mixes in the PathVisitor trait? 对我来说,莫名其妙的是:1)为什么他在同时混合PathVisitor特性的同时扩展SimpleFileVisitor? 2) Are we not trying to ask class Simple to honor both SimpleVisitor contract and FileVisitor trait unimplemented methods, when they are the same methods? 2)当它们是相同的方法时,我们是否不想让Simple类同时遵守SimpleVisitor合同和FileVisitor特质未实现的方法? 3) He wraps the Simple Class, a bunch of vals to represent the return types of the SimpleFileVisitor methods and an apply method. 3)他包装了简单类,一堆val以表示SimpleFileVisitor方法和apply方法的返回类型。 Okay, so what do you think is the idea behind this kind of structure? 好的,那么您认为这种结构背后的想法是什么?

I would really like to use the structure laid out by PaulP, but this is baffling. 我真的很想使用PaulP提出的结构,但这令人困惑。 It needs some cleanup perhaps. 它可能需要一些清理。 Please advise. 请指教。

The reason to do things this way is to provide a seamless Scala experience. 这样做的原因是为了提供无缝的Scala体验。 First, instead of abstracting over whichever T you might have a visitor for, the first trait specifies paths. 首先,第一个特征指定路径,而不是抽象出可能有访客的T If you're really only interested in paths, it's nice to not have to worry about generics. 如果您真的只对路径感兴趣,那就不必担心泛型了。

Then he provides the constants for you in Scala style so you don't have to grab them from Java. 然后,他以Scala样式为您提供了常量,因此您不必从Java中获取它们。

And he gives you a Path-specific SimpleFileVisitor without any extra work by just mixing in the PathVisitor trait. 他通过混合PathVisitor特性为您提供了特定SimpleFileVisitor路径的SimpleFileVisitor而无需进行任何额外的工作。

Now, the question remains: why do this rather than just say 现在的问题仍然是:为什么这样做,而不是仅仅说

type PathVisitor = java.nio.file.FileVisitor

There are two reasons. 有两个原因。 First, types aliases aren't really first-class language constructs, so you'll tend to see the Java type instead of the Scala one (slightly less nice). 首先,类型别名并不是真正的一流语言构造,因此您将倾向于看到Java类型而不是Scala类型(稍微不太友好)。 Also, if you set it up this way you can more easily add functionality into the framework later. 另外,如果以这种方式进行设置,则以后可以更轻松地向框架中添加功能。 If you're sure you won't want to add anything, there's less argument to do it this way. 如果您确定自己不想添加任何内容,那么使用这种方法的论点就更少了。

Now, for specific questions: 现在,对于特定问题:

  1. We mix in PathVisitor so we have a Scala-specific type that we can move around and manipulate; 我们混入PathVisitor,因此我们有一个Scala特定类型,可以四处移动和操作; we get the implementations from the Java SimpleFileVisitor but make it pick up the Scala trait. 我们从Java SimpleFileVisitor获取实现,但使它具有Scala特性。

  2. Asking to honor multiple methods which match isn't a problem; 要求遵守多种匹配方法不是问题。 the same method can be part of the API of multiple traits. 相同的方法可以是多个特征的API的一部分。 The key is whether you can use the trait you want (ie PathVisitor; answer is "yes"). 关键是您是否可以使用所需的特征(即PathVisitor;答案为“是”)。

  3. Scala-style constants provided locally help clean up your imports and provides a more seamless experience, as does the apply -style builder instead of new . 本地提供的Scala样式常量有助于清理导入并提供更无缝的体验, apply样式生成器(而不是new

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM