2015-03-30 131 views
1

我每天都在斯卡拉學習新東西。我正在採用的當前路線是從Java nio中提取功能,並使Scala實現完全脫離它們。我觀察過其他Scala專家是如何使用java.nio.files包的,以及FileVisitor接口如何遞歸地遍歷子目錄和文件的嵌套目錄結構。斯卡拉:特質擴展java.nio.file.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 歡迎來到Scala版本2.10.2(Java HotSpot™64位服務器VM,Java 1.7.0_71)。 輸入表達式來評估它們。 類型:help獲取更多信息。

scala> import java.nio.file。{FileVisitor}; 進口java.nio.file.FileVisitor

階>進口java.nio.file.Path 進口java.nio.file.Path

階>性狀PathVisitor延伸FileVisitor的[路徑] 定義性狀PathVisitor

斯卡拉>


有了這樣的方式,我現在看了一下源FileVisitor.java。這裏是:這是保羅耐人尋味的地方。下面的代碼後面的解釋。

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

} 

這一切後,我提出以下意見: 類的簡單擴展SimpleFileVisitor,這是Java FileVisitor的接口的實現

此外,在特質PathVisitor paulp混合,其方法定義與Java FileVisitor界面中的完全相同。

這裏有什麼讓我感到困惑的是: 1)爲什麼他在擴展SimpleFileVisitor的同時也混入了PathVisitor特性? 2)我們是不是試圖問類SimpleVisitor契約和FileVisitor trait未實現方法,當它們是相同的方法嗎? 3)他包裝了Simple Class,一組val代表SimpleFileVisitor方法的返回類型和一個apply方法。好的,你認爲這種結構背後的想法是什麼?

我真的很想使用PaulP制定的結構,但這是令人困惑的。它可能需要一些清理。 請指教。

+0

保羅這樣做是「正確的方式」,我希望我有時間來解釋爲什麼。 (有不止一個正確的方法,但這是其中之一。)我希望別人會!關鍵是要思考這些事情爲您面向Scala的API所做的工作。如果你自己想出來,請寫一個答案! – 2015-03-30 19:44:06

+0

感謝您的洞察。我一定會報告我的發現。這是一個令人興奮的搜索 – user3825558 2015-03-30 19:51:25

+0

我應該說 - 我是_assuming_這是正確的方式,因爲它如何適合一個我沒有的更大的圖片。 – 2015-03-30 20:07:30

回答

1

這樣做事情的理由是提供無縫的Scala體驗。首先,不要抽象出你可能有訪問者的任何一個,第一個特徵指定路徑。如果你真的只對路徑感興趣,不用擔心泛型。

然後,他爲您提供了Scala風格的常量,因此您無需從Java中獲取它們。

他給你一個路徑專用SimpleFileVisitor沒有任何額外的工作,只需混合在PathVisitor特質。

現在,問題是:爲什麼而不是僅僅說

type PathVisitor = java.nio.file.FileVisitor 

有兩個原因。首先,類型別名不是真正的一流語言結構,所以你會傾向於看到Java類型而不是Scala(稍微不好)。另外,如果你這樣設置,你可以稍後更輕鬆地將功能添加到框架中。如果你確定你不想添加任何東西,那麼用這種方法就沒有什麼爭論了。

現在,對於具體的問題:

  1. 我們PathVisitor混合,所以我們有我們可以移動和操控特定的斯卡拉型;我們從Java SimpleFileVisitor獲得了實現,但是使它獲得了Scala特性。

  2. 要求兌現匹配的多種方法不是問題;相同的方法可以是多個特徵的API的一部分。關鍵是你是否可以使用你想要的特質(即PathVisitor;答案是「是」)。

  3. 本地提供的Scala式常量可幫助清理導入並提供更加無縫的體驗,apply風格的構建器代替new

+0

非常好的解釋。感謝您抽出寶貴的時間。 「有兩個原因:首先,類型別名不是真正的一流的語言結構,所以你會傾向於看到Java類型而不是Scala(不太好)。另外,如果你這樣設置它,你稍後可以更容易地將功能添加到框架中,如果你確定你不想添加任何東西,那麼用這種方法就沒有什麼爭論了。「這是最好的部分。 – user3825558 2015-04-03 13:24:55

+0

「要求尊重多種匹配方法不是問題;」 - 令人驚歎。我不知道這不會是一個問題,甚至是理智的。 – user3825558 2015-04-03 13:26:07