Scala 带未来的隐式转换

Scala 带未来的隐式转换,scala,future,implicit-conversion,Scala,Future,Implicit Conversion,从DB模型到应用程序模型的隐式转换有问题: override implicit def dbBook2AppBook(book: Book): BookApp = { val author = Await.result(authRep.getById(book.authID),1 seconds) BookApp(book.id.get, book.title, AuthorApp(author.get.id,author.get.nam

从DB模型到应用程序模型的隐式转换有问题:

  override implicit def dbBook2AppBook(book: Book): BookApp = {
      val author = Await.result(authRep.getById(book.authID),1 seconds)
      BookApp(book.id.get, book.title, 
              AuthorApp(author.get.id,author.get.name,author.get.surname), book.available)
  }
基本上,我想将Book转换为BookApp:

case class BookApp(id: Int,
                   title: String,
                   author: AuthorApp,
                   var available: Boolean)

case class Book(id: Option[Int] = None, title: String, authID: Int, available: Boolean)
正如你们所看到的,我的Book类有作者ID,我希望我的BookApp里面有AuthorApp对象。我需要做的是从数据库作者那里获取,同时从书中进行转换。通过
authRep:authorrepository
从数据库中获取
Future[Author]

我的问题是,是否有更好的方法从转换中获取BookApp而不需要使用wait for Author对象?有什么建议吗

编辑 对于“Jon Anderson”的回答,我不能从
Future[Book]
转换到
Future[BookApp]
,因为当我从数据库中获取多行数据时,我收到的是
Future[Seq[Book]]
,那么转换就不起作用了。其他信息,我仍然保留整个应用程序的未来,因为当我进行转换时,我会执行以下操作:

  def findBooks(title: Option[String], authorName: Option[String], 
                authorSurname: Option[String], available: Option[Boolean])
                : Future[Seq[BookApp]] = {
    bookRep.findBooks(title,authorName,authorSurname,available)
                      .map(x => x.map( y => y: BookApp))
  }

所以,通过映射对对象进行转换,但仍然返回转换后的未包装对象。主要的问题是转换中的等待,所以主要的问题是,我怎样才能摆脱它?

你应该在应用层一路保留未来。在这种情况下,用于理解的
非常有效

override implicit def dbBook2AppBook(bookFuture: Future[Book]): Future[BookApp] = { 
    for {
       book <- bookFuture
       author <- authRep.getById(book.authID)
       //any other futures needed to create APP model here...
    } yield {
        BookApp(book.id.get, book.title, AuthorApp(author.get.id,author.get.name,author.get.surname), book.available)
    }
}
重写隐式def dbBook2AppBook(bookFuture:Future[Book]):Future[BookApp]={
为了{

书正如你发现的那样,思想类型:你不能

首先,忘记在设计中使用隐式转换,直到您更熟悉这些语言,它们在这里对您没有帮助。(永远忘记隐式转换…)

这里一种可能的方法是在
Future
上下文中使用
dbBook2FutureAppBook(book:book):Future[BookApp]

使用
Future#flatMap
Future可以将
Future[Seq[Book]]]
转换为
Future[Seq[Bookapp]]

val fsb: Future[Seq[Book]] = ...

val fsa: Future[Seq[Bookapp]] =
  fsb.flatMap { books => 
    Future.sequence(books.map(dbBook2FutureAppBook))
  }

这回答了您关于
Future
的问题,但请注意,这将在
Future[Seq[book]]
中为每本书发出一个数据库查询,这是一个糟糕的想法。您可能想编写一个
Seq[book]=>Seq[Bookapp]
手工查询。

是的,我知道如何进行从未来到未来的隐式转换,情况是我不想:)原因是,有时我获得未来[Seq[Book]]从数据库,那么这种转换与未来将不起作用:)我将添加这个问题你能告诉我为什么我应该永远忘记隐式转换我会很高兴:)在这种情况下,我有不同的模型连接到数据库和不同的应用程序中,我认为隐式转换真的很好:)那么magn呢et模式?你能告诉我为什么隐式转换是个坏主意吗?请提出一个新问题“在我的设计中何时可以使用隐式转换?”.我不像@OlivierBlanvillain那样虔诚地看待隐式转化的恐怖。我认为这是可以做得对的,但我同意在这里根本没有必要这样做。你尤其要小心,因为你对Scala来说似乎是新手。这将帮助你开始理解隐式转化在哪些方面有用,哪些方面可能危险。@Vidya但正如你们所看到的,我正在将模型对象转换为将在应用程序中使用的对象。除了隐式转换之外,我还能使用什么?在我需要的任何地方都使用显式转换?我使用它是因为我希望我的存储库只看到DB模型,而服务和控制器只看到应用程序模型。老实说,我的第一选择是只有一个类看起来像你的
BookApp
类(除了
var
)让转换的概念——隐式的或其他的——成为现实。对我来说,权衡是值得的。我甚至可能会根据痛苦的程度重新构建我的数据模型。无论哪种方式,转换都会带来很多复杂性,但在我看来并没有真正的收益,@OlivierBlanvillain的解决方案,尽管在技术上适合您的情况正如他所指出的那样,在这方面,这确实是次优的。