2017-04-08 46 views
0

下面的代码无法编译。覆盖特征中的隐式抽象成员 - 注入隐式依赖(类型实例) - 如何使其工作?

此代码的目的是将隐式依赖注入到UseImplicit。 换句话说,它是类型实例的依赖注入。

trait StuffProvider[T]{ 
    implicit val provideStuff:() => T 
} 

trait UseImplicit{ 
    implicit val gimmiString: StuffProvider[String] // implicit dependency 
    implicit val gimmiInt: StuffProvider[Int] 
    def foo[T:StuffProvider]() :T = implicitly[StuffProvider[T]].provideStuff() 
} 

object Main{ 

    object StringProvider extends StuffProvider[String]{ 
    implicit val provideStuff:() => String=() => "bla" 
    } 

    object IntProvider extends StuffProvider[Int]{ 
    implicit val provideStuff:() => Int=() => 42 
    } 

    object UI extends UseImplicit { 
    implicit val gimmiString=StringProvider // injection 
    implicit val gimmiInt=IntProvider 
    } 

    val f:Int=UI.foo[Int]() // Error:(27, 15) could not find implicit value for evidence parameter of type StuffProvider[T] 

} 

但这编译就好:

trait UseImplicit2{ 
    implicit val gimmiString: String 
    def foo() :String = implicitly[String] 
} 

object Main2{ 

    object UI extends UseImplicit2 { 
    override implicit val gimmiString:String = "s" 
    } 
    val f=UI.foo() // this compiles just fine 
} 

我看不出两者有什么代码之间的差异,它们具有相同的结构。

为什么第二次编译和第一次没有?

我该如何进行第一次编译?

我的目标是,我可以将implicits注入到UseImplicits的实现中。这样我可以提供几个实现(测试,生产)。

斯卡拉小提琴是在这里:https://scalafiddle.io/sf/dm3OJSF/1

回答

2

导入UI implicits(由import UI._)转换成电流范围,正确调用UI.foo()之前,应该解决您的问题。


你可以注入所需UseImplicit(例如,进入Foo类),并把它作为:

case class Foo(ui: UseImplicit) { 
    import ui._ 
    val f: Int = ui.foo[Int]() //Use your injected `UseImplicit` 
} 
+0

正确的,但我想绕过UI在Useimplicit'的'形式,如果我导入一个特定的实现,然后我不能注入作为依赖的暗示,这将是整个故事的点 – jhegedus

+0

@jhegedus又增加了一个例子。 –

+0

谢谢,我需要看看我到家时是否可以完成这项工作,目标是将蛋糕模式与implicits结合起来,所以'UseImplicit'也会通过自我注释注入 – jhegedus