我用Scala编写了以下内容:
implicit class Appender[A, B](x: (Growable[A], Growable[B])) {
def ++=(y: (TraversableOnce[A], TraversableOnce[B])): (Growable[A], Growable[B]) =
(x._1 ++= y._1, x._2 ++= y._2)
}但是Scala不接受x._2 ++= y._2,抱怨说:Expression of type Growable.this.type doesn't conform to expected type Growable[B]。
我也试过:

为此,IntelliJ建议返回类型的(Growable.this.type, Growable.this.type),这将导致其他问题。
我遗漏了什么?将此++=操作添加到2 Growable的Tuple2中的正确方法是什么?
是否有一种方法可以编写这种“提升”,但也可以将其推广到操作(此处为++=)?这将是一些隐式Lift,它可以将操作从对内的类型传递到对类型本身。这在Scala中有可能吗?
发布于 2018-11-12 02:43:21
您的第一个代码片段对我来说编译和工作都很好,尽管IntelliJ对其进行了强调。
但是,这段代码的问题是,它丢失了关于第一对具体类型的信息。结果显示为不透明的(Growable[A], Growable[B])。
为了保留类型,您可以使用类似于第二个片段的东西。问题是编译器似乎无法将隐式转换应用于一对Growable子类型。但是,如果您试图显式地创建Appender,它可以工作:
object Test {
implicit class Appender[
A, GA <: Growable[A],
B, GB <: Growable[B]
](x: (GA, GB)) {
def ++=(y: (TraversableOnce[A], TraversableOnce[B])): (GA, GB) = {
(x._1 ++= y._1, x._2 ++= y._2)
}
}
def main(args: Array[String]): Unit = {
val a = (ArrayBuffer(1,2,3), ArrayBuffer("a","b","c"))
println(new Appender(a).++=((List(4,5,6), List("d","e","f"))))
}
}您可以通过使用组合类型x定义GA with Growable[A]的部分来帮助编译器。在这种情况下,编译器使用声明的Growable[A]部分检测并正确应用隐式转换。您仍然可以访问完整类型的GA,以便从该方法返回:
object Test {
implicit class Appender[
A, GA <: Growable[A],
B, GB <: Growable[B]
](x: (GA with Growable[A], GB with Growable[B])) {
def ++=(y: (TraversableOnce[A], TraversableOnce[B])): (GA, GB) = {
(x._1 ++= y._1, x._2 ++= y._2)
}
}
def main(args: Array[String]): Unit = {
val a = (ArrayBuffer(1,2,3), ArrayBuffer("a","b","c"))
println(a ++= (List(4,5,6), List("d","e","f")))
}
}附加:
至于你的奖金问题,我不认为有一个简单的方法来自动创建所有的方法。也许你可以用宏做点什么,但我不确定。但是我相信您可以使用一些帮助方法来大大简化方法定义。没有那么多方法可以对Growable进行有意义的定义,因此我相信有一个完整的定义:
implicit class Appender[
A, GA <: Growable[A]
](x: (GA with Growable[A], GA with Growable[A])) {
private def wrap[B, R](f: GA => B => R): ((B, B)) => (R, R) =
y => (f(x._1)(y._1), f(x._2)(y._2))
val ++= = wrap(_.++=)
val += = wrap(_.+=)
def clear(): Unit = {
x._1.clear()
x._2.clear()
}
}如果你有其他手术
def myOpDef[A, GA <: Growable[A]](ga: GA, traversable: TraversableOnce[A]): GA = ???您还可以将其添加到Appender定义中(但这似乎有点棘手):
val myOp = wrap(ga => myOpDef(ga, _))或
val myOp = wrap(myOpDef[A, GA].curried)https://stackoverflow.com/questions/53254858
复制相似问题