在特征和方法中实现泛型
Implement generics in trait and method
我已经在 scala 用户论坛上发布了这个问题,
https://groups.google.com/forum/#!topic/scala-user/xlr7KmlWdWI
我收到了一个令我满意的答复。但是,与此同时,我想确定这是否是唯一的结论。谢谢
我的问题是,我有,
trait Combinable[A] {
def join[B](l: List[A]): B
}
例如,当我使用 A 作为 String 和 B 作为 Int 实现此特征时,
class CombineString extends Combinable[String] {
override def join[Int](strings: List[String]) = string.size
}
显然,Int,在 join 方法旁边,不是 Scala 整数 class 和
编译此代码将失败。或者,我可以将我的特征重写为
trait Combinable[A, B] {
def join(l: List[A]): B
}
或
trait Combinable[A] {
def join[B](l: List[A])(f: List[A] => B): B
}
我的问题是,如何按原样实现第一个示例中定义的特征?如果第一个例子因为它的定义方式而没有实际用途,为什么编译器不抱怨?再次感谢。
My question is, how can I implement the trait as defined in the first example as it is?
class CombineString extends Combinable[String] {
override def join[B](strings: List[String]) = null.asInstanceOf[B]
// or, for that matter, anything and then .asInstanceOf[B]
}
编译器怎么知道这不是你想要的?
您不能指望编译器理解哪些类型组合对您有意义,但您可以根据多参数隐式将这种意义指定为类型之间的关系。
结果基本上是您拒绝的两种方法的组合,但具有所需的语法。
两个被拒绝的形式中的第一个成为隐式类型:
trait Combine[A, B] {
def apply(l: List[A]): B
}
接下来您可以定义适当的类型组合及其含义
implicit object CombineStrings extends Combine[String, String] {
def apply(l: List[String]) = l.mkString
}
implicit object CombineInts extends Combine[Int, Int] {
def apply(l: List[Int]) = l.sum
}
implicit object CombinableIntAsString extends Combine[Int, String] {
def apply(l: List[Int]) = l.mkString(",")
}
最后我们修改了第二个被拒绝的表单,它隐藏了隐式结果的 f
参数:
trait Combinable[A] {
def join[B](l: List[A])(implicit combine: Combine[A, B]): B = combine(l)
}
现在你可以定义
val a = new Combinable[String] {}
val b = new Combinable[Int] {}
并检查
a.join[String](List("a", "b", "c"))
b.join[Int](List(1, 2, 3))
b.join[String](List(1, 2, 3))
运行良好,而
a.join[Int](List("a", "b", "c"))
让编译器哭泣,直到你能提供 String
和 Int
之间关系的隐含值
的实际使用证据
我已经在 scala 用户论坛上发布了这个问题,
https://groups.google.com/forum/#!topic/scala-user/xlr7KmlWdWI
我收到了一个令我满意的答复。但是,与此同时,我想确定这是否是唯一的结论。谢谢
我的问题是,我有,
trait Combinable[A] {
def join[B](l: List[A]): B
}
例如,当我使用 A 作为 String 和 B 作为 Int 实现此特征时,
class CombineString extends Combinable[String] {
override def join[Int](strings: List[String]) = string.size
}
显然,Int,在 join 方法旁边,不是 Scala 整数 class 和 编译此代码将失败。或者,我可以将我的特征重写为
trait Combinable[A, B] {
def join(l: List[A]): B
}
或
trait Combinable[A] {
def join[B](l: List[A])(f: List[A] => B): B
}
我的问题是,如何按原样实现第一个示例中定义的特征?如果第一个例子因为它的定义方式而没有实际用途,为什么编译器不抱怨?再次感谢。
My question is, how can I implement the trait as defined in the first example as it is?
class CombineString extends Combinable[String] {
override def join[B](strings: List[String]) = null.asInstanceOf[B]
// or, for that matter, anything and then .asInstanceOf[B]
}
编译器怎么知道这不是你想要的?
您不能指望编译器理解哪些类型组合对您有意义,但您可以根据多参数隐式将这种意义指定为类型之间的关系。
结果基本上是您拒绝的两种方法的组合,但具有所需的语法。
两个被拒绝的形式中的第一个成为隐式类型:
trait Combine[A, B] {
def apply(l: List[A]): B
}
接下来您可以定义适当的类型组合及其含义
implicit object CombineStrings extends Combine[String, String] {
def apply(l: List[String]) = l.mkString
}
implicit object CombineInts extends Combine[Int, Int] {
def apply(l: List[Int]) = l.sum
}
implicit object CombinableIntAsString extends Combine[Int, String] {
def apply(l: List[Int]) = l.mkString(",")
}
最后我们修改了第二个被拒绝的表单,它隐藏了隐式结果的 f
参数:
trait Combinable[A] {
def join[B](l: List[A])(implicit combine: Combine[A, B]): B = combine(l)
}
现在你可以定义
val a = new Combinable[String] {}
val b = new Combinable[Int] {}
并检查
a.join[String](List("a", "b", "c"))
b.join[Int](List(1, 2, 3))
b.join[String](List(1, 2, 3))
运行良好,而
a.join[Int](List("a", "b", "c"))
让编译器哭泣,直到你能提供 String
和 Int
之间关系的隐含值