2015-01-16 48 views
0

我想知道如果我有類似的情況下,我如何可以防止循環隱式轉換?在隱式轉換中防止循環

編輯:這是用於在用作ORTO實體的ORM實體和案例類之間轉換的一些上下文。

class Author(var name: String) { 
    def books : List[Book] = List(new Book("title", this))// get books 
} 

class Book(var title: String, var author: Author) 

case class DTOBook(title: String, author: Option[DTOAuthor]) 

case class DTOAuthor(name: String, books: List[DTOBook]) 

implicit def author2Author(author: Author) : DTOAuthor = { 
    DTOAuthor(author.name, author.books.map(x => x : DTOBook) : List[DTOBook]) 
} 

implicit def book2Book(book: Book) : DTOBook = { 
    DTOBook(book.title, Option(book.author : DTOAuthor)) 
} 

val author: DTOAuthor = new Author("John Brown") 

回答

1

問題是你的數據結構是循環的。一個Author包含Book S的包含Author,其中包含Book S,等等。

所以,當你轉換到AuthorDTOAuthor,這樣的事情發生了:

  • author2Author
  • 中的第一個author2Author致電,author.books必須轉換爲List[DTOBook]
  • 這意味着每個Book內部的author必須轉換爲DTOAuthor
  • 重複

您可以通過被嵌套在每個Bookbooks列表是空的author解決此。要做到這一點,您必須在一個地方取消對隱式轉換的依賴,並手動創建沒有書籍的嵌套DTOAuthor

implicit def book2Book(book: Book) : DTOBook = { 
    DTOBook(book.title, Option(DTOAuthor(book.author.name, Nil))) 
} 
0

這不是一個隱含的問題,它是一個數據結構問題;你的數據結構是循環的,這使事情變得複雜。你會遇到與「正常」,非隱式轉換函數完全相同的問題。

您可以濫用可變性,但「正確」的方式可能是https://www.haskell.org/haskellwiki/Tying_the_Knot中描述的「信用卡轉換」(請記住,默認情況下,Scala並非懶惰,因此您需要通過傳遞函數來使用顯式懶惰) 。但最好的解決方案可能是看看你是否可以避免在數據結構中存在這些循環。在一個不可變的數據結構中,它們是痛苦的祕訣,例如想一想如果你做

val updatedAuthor = dtoAuthor.copy(name="newName") 
updatedAuthor.books.head.author.get.name 

作者的名稱已更改會發生什麼,但是這本書仍然認爲它的作者有老人的名字!