我可以 "Pimp my Library" 参数化特征,方法返回 this.type 吗?
Can I "Pimp my Library" on a parameterized trait with method returning this.type?
我想使用 Pimp my Library 模式扩展我的 参数化 特征 Field[T]
,方法返回 this.type
。但我坚持编译器错误。我尝试了一些变体,但没有成功。
我做错了吗?还是问不可能的事?
这是我的测试示例:
trait Field[T]
class IntField extends Field[Int] {
def getInt = 5
}
// Variant 1: return field.type
object Var1 {
implicit class RichField[T](val field: Field[T]) {
def bar(fn: T => String): field.type = {
// some actions using T
field
}
}
new IntField().bar(_.toString).getInt // Error: value getInt is not a member of Field[Int]
}
// Variant 2: use two type parameters
object Var2 {
implicit class RichField[T, F <: Field[T]](val field: F) {
def bar(fn: T => String): F = {
// some actions using T
field
}
}
new IntField().bar(_.toString).getInt // <-- Error: value bar is not a member of IntField
}
// Variant 3: use higher kinds
object Var3 {
import scala.language.higherKinds
implicit class RichField[F[X] <: Field[X], T](val field: F[T]) {
def bar(fn: T => String): F[T] = {
// some actions using T
field
}
}
new IntField().bar(_.toString).getInt // <-- Error: value getInt is not a member of Field[Int]
}
更新:参数T
对方法bar
很重要,不能忽略。
在变体 2 中,您没有在任何地方使用 T
。把它去掉,编译器就不会再混淆了:
implicit class RichField[F <: Field[_]](val field: F) {
def bar: F = field
}
更新:如果您确实需要 T
,正如您在评论中提到的,可能的解决方法是:
implicit class RichField[T, F <: Field[_]](val field: F with Field[T]) {
def bar(fn: T => String): F = {
// some actions using T
field
}
}
这是一个证明它按预期工作的证明(在你的例子中使用 toString
并不是一个好的测试,因为 toString
在每个 class 上可用,所以即使编译器推断 Any
代码会被编译):
scala> case class Foo(name: String)
defined class Foo
scala> class FooField extends Field[Foo] {
| def getInt = 5
| }
defined class FooField
scala> new FooField().bar(_.name).getInt
res8: Int = 5
我想使用 Pimp my Library 模式扩展我的 参数化 特征 Field[T]
,方法返回 this.type
。但我坚持编译器错误。我尝试了一些变体,但没有成功。
我做错了吗?还是问不可能的事?
这是我的测试示例:
trait Field[T]
class IntField extends Field[Int] {
def getInt = 5
}
// Variant 1: return field.type
object Var1 {
implicit class RichField[T](val field: Field[T]) {
def bar(fn: T => String): field.type = {
// some actions using T
field
}
}
new IntField().bar(_.toString).getInt // Error: value getInt is not a member of Field[Int]
}
// Variant 2: use two type parameters
object Var2 {
implicit class RichField[T, F <: Field[T]](val field: F) {
def bar(fn: T => String): F = {
// some actions using T
field
}
}
new IntField().bar(_.toString).getInt // <-- Error: value bar is not a member of IntField
}
// Variant 3: use higher kinds
object Var3 {
import scala.language.higherKinds
implicit class RichField[F[X] <: Field[X], T](val field: F[T]) {
def bar(fn: T => String): F[T] = {
// some actions using T
field
}
}
new IntField().bar(_.toString).getInt // <-- Error: value getInt is not a member of Field[Int]
}
更新:参数T
对方法bar
很重要,不能忽略。
在变体 2 中,您没有在任何地方使用 T
。把它去掉,编译器就不会再混淆了:
implicit class RichField[F <: Field[_]](val field: F) {
def bar: F = field
}
更新:如果您确实需要 T
,正如您在评论中提到的,可能的解决方法是:
implicit class RichField[T, F <: Field[_]](val field: F with Field[T]) {
def bar(fn: T => String): F = {
// some actions using T
field
}
}
这是一个证明它按预期工作的证明(在你的例子中使用 toString
并不是一个好的测试,因为 toString
在每个 class 上可用,所以即使编译器推断 Any
代码会被编译):
scala> case class Foo(name: String)
defined class Foo
scala> class FooField extends Field[Foo] {
| def getInt = 5
| }
defined class FooField
scala> new FooField().bar(_.name).getInt
res8: Int = 5