类型类和隐式与单一实例类型/案例对象



我正在尝试实现一个适用于案例对象而不是类的类型类。它有点工作。 但是,当我将 case 对象本身传递给函数时,它起作用了,当我尝试传递具有它无法编译的基本特征类型的对象时。

object Test {
sealed trait MyType
case object Type1 extends MyType
case object Type2 extends MyType
trait Builder[A] {
def build: String
}
object Builder {
implicit  val type1Builder: Builder[Type1.type] = new Builder[Type1.type] {
def build: String = s"building1"
}
implicit val type2Builder: Builder[Type2.type] = new Builder[Type2.type] {
def build: String = s"building2"
}
def build[A](a: A)(implicit builder: Builder[A]) = builder.build
}
import Builder._
// Compiles
def test[T <: MyType](t:Type2.type): Unit = {
println(Builder.build(t))
}
// Doesn't compile - 'could not find implicit value for parameter builder ' 
def test2[T <: MyType](t:MyType): Unit = {
println(Builder.build(t))
}
}

这是因为 scala 中的类型参数在默认情况下是不变的,这意味着:

Builder[Type1.type] 不是 Builder[MyType] 的子类型。

在这个代码块中,你需要一个 Builder[MyType],而 type1Builder 和 type2Builder 都不是 Builder[MyType] 的子类型:

def test[T <: MyType](t:MyType): Unit = {
println(Builder.build(t))
}

你可以使 Builder 的类型参数协变 (Builder[+A](,但是,type1Builder 和 type2Builder 都将是该隐式参数的候选项,因此它将再次失败。

您需要做的是在测试方法中使用上下文边界,而不是上限类型边界,如下所示:

def test[T : Builder](t: T): Unit = {
println(Builder.build(t))
}

这意味着测试接收一个 T 类型,它是生成器类型类的成员,Type1和 Type2 都是生成器类型类的成员,因为在隐式作用域中有一个 Builder[Type1.type] 和一个 Builder[Type2.type]。

如果你还想限制测试,所以你只能用MyType的实现来调用它,你可以同时使用上限类型边界和上下文边界:

def test[T <: MyType : Builder](t: T): Unit = {
println(Builder.build(t))
}

test(Type1) // building1
test(Type2) // building2

不知何故,这对我有用。不知道为什么

def test2[T <: MyType : Builder ](t2:T): Unit = {
println(Builder.build(t2))
}

相关内容

  • 没有找到相关文章

最新更新