Scala 蛋糕模式和自类型注释

标签 scala dependency-injection cake-pattern

我正在尝试遵循此 blog 中的示例。我理解这个示例,但在实现它时遇到困难。

trait Database {
  // ...
}

trait UserDb {
  this: Database =>
    // ...
}

trait EmailService {
  this: UserDb =>
    // Can only access UserDb methods, cannot touch Database methods
}

该示例提到完整的数据库功能将从 EmailService 中隐藏 - 这就是我所追求的,但不知道如何正确实现这些特征。

这就是我尝试过的实现:

trait Database {
    def find(query: String): String
  }

  trait UserDb {
    this: Database =>
  }

  trait EmailService {
    this: UserDb =>
  }

  trait MongoDatabase extends Database {

  }

  trait MongoUserDb extends UserDb with MongoDatabase{

  }

  class EmailServiceImpl extends EmailService with MongoUserDb {
    override def find(query: String): String = {
      "result"
    }
  }

这对我来说看起来很奇怪,因为 MongoDatabase 特征没有要求 find 实现,当我实现 EmailService 时,系统提示我进行 find实现,尽管示例提到这将从 EmailService 中隐藏。我在这里缺少什么?

阅读完您的评论后,我正在尝试在一个更接近我实际尝试做的示例上实现我正在尝试理解的内容。

第一个片段无法编译,但第二个片段会... 归根结底,我希望有不同的 Repository 实现,我可以在它们依赖的数据库之间切换,我是否接近下面的代码片段之一?

trait Database {
    def find(s: String): String
  }

  trait Repository {
    this: Database =>
  }

  class UserRepository extends Repository {
    def database = new MongoDB

    class MongoDB extends Database {
      def find(s: String): String = {
        "res"
      }
    }
  }


trait Repository {
    def database: Database

    trait Database {
      def find(s: String): String
    }
  }

  trait UserRepository extends Repository {
    def database = new MongoDB

    class MongoDB extends Database {
      def find(s: String): String = {
        "res"
      }
    }
  }

最佳答案

如上所述,MongoUserDB 不会要求实现,因为它是一个特征。然而,由于 EmailServiceImpl 扩展了它需要提供实现的特征。 您正在寻找的内容可以通过添加另一个抽象来完成。我使用 serviceDAO 架构来完成此操作。 下面是一个工作示例,您可以使用它来看看它是否适合您。

//All future versions of DAO will extend this
trait AbstractDAO{
  def getRecords:String
  def updateRecords(records:String):Unit
}
//One concrete version
trait concreteDAO extends AbstractDAO{
  override def getRecords={"Here are DB records"}
  override def updateRecords(records:String){
    //Actual DB calls and operations
    println("Updated "+records)
  }
}
//Second concrete version
trait concreteDAO1 extends AbstractDAO{
  override def getRecords={"DB Records returned from DAO2"}
  override def updateRecords(records:String){
    //Actual DB calls and operations
    println("Updated via DAO2"+records)
  }
}
//This trait just defines dependencies (in this case an instance of AbstractDAO) and defines operations based over that
trait service{
  this:AbstractDAO =>

  def updateRecordsViaDAO(record:String)={  
  updateRecords(record) 
  }
  def getRecordsViaDAO={
  getRecords
  }
}

//Test Stub
object DI extends App{
  val wiredObject = new service with concreteDAO //injecting concrete DAO to the service and calling methods
  wiredObject.updateRecords("RECORD1")
  println(wiredObject.getRecords)

  val wiredObject1 = new service with concreteDAO1
  wiredObject1.updateRecords("RECORD2")
  println(wiredObject1.getRecords)

}

编辑---

这是您可能想要实现的代码,

    trait Database {
    def find(s: String): String
  }

trait MongoDB extends Database{
  def find(s:String):String = { "Test String" }
}
trait SQLServerDB extends Database{
  def find(s:String):String = { "Test String2" }
}

  trait Repository {
    this: Database =>
  }

  class UserRepository extends Repository with MongoDB{  //  UserRepository is injected with MongoDB here
    find("call MongoDB") //This call will go to the find method in MongoDB trait
  }

  class UserRepository1 extends Repository with SQLServerDB{  //  UserRepository is injected with SQLServerDB here
    find("call SQLServerDB") //This call will go to the find method in SQLServerDB trait
  }

关于Scala 蛋糕模式和自类型注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36573174/

相关文章:

Android 输血

php - 无法将路由器服务传递给 symfony 2.6 中的 Twig 扩展

scala - 以蛋糕模式抽象数据库客户端

Scala 蛋糕图案 : Splitting large components into separate files

scala - 在 tomcat 7 上使用 akka 部署喷雾,无法从 Rest API 获得响应

scala - Phantom for Cassandra 中的多个 Order By 子句

c# - 依赖注入(inject) : static parameters and services

scala - 在 Scala 中使用 Cake 模式和函数之间的区别 - 为什么 Cake 模式有用?

scala - PlayFramework + ScalaTest + ScalaCheck

scala - 如何返回 Id 的序列生成