如何扩展 List[Double]
how to extend List[Double]
我想要一个在功能上扩展 List[Double]
并增加一些功能的自定义 class。我对 Pimp My Library 的理解会引导我构建如下内容:
implicit class MahThing(list:List[Double]) {
def mahStuff = ...
}
问题是,现在到处都导入 MahThing
,所有 List[Double]
都可以选择 mahStuff
。
同上:
class MahThing(list:List[Double]) {
def mahStuff ...
}
implicit def toThing(list:List[Double]) = new MahThing(list)
现在,list.toThing
生产 MahThing
,但 MahThing
不能做 List
y 东西。煞费苦心地将 MahThing
中的 List
操作定义为 list.operation
是很费力的。出于某种原因,使用 MahThing
的实例,它让我例如在 map
操作期间声明变量类型。
我真正需要的是扩展 List[Double]
的确切功能。本该 MahThing
的事情却 mahStuff
去做了,而没有其他人去做。另外,MahThing
在其他方面都和 List
一样。
使用隐式转换是扩展 List[T](在你的情况下 T 是 Double)功能的正确方法(作为 List[T] final,它不能被扩展)并且如你所见
everywhere MahThing is imported, all List[Double]s have the option to
do mahStuff.
但是,如果我没弄错的话,你不希望所有的 List[Double] 都像那样,所以我的建议是创建一个 MahDouble class 来接受 Double 作为参数并将两种方式隐式转换为 Double
object MahDouble {
implicit def toMah(d: Double): MahDouble = new MahDouble(d)
implicit def backToDouble(m: MahDouble): Double = m.d
}
case class MahDouble(d: Double)
然后您可以将该 MahDouble 用作您的 MahThing List 的类型,并将其从 List[MahDouble] 隐式转换。
object MahThing {
implicit def toThing(list:List[MahDouble]): MahThing = new MahThing(list)
}
case class MahThing(list:List[MahDouble]) {
def mahStuff ...
}
对于任何 aspect MahDouble 都将作为 Double,但只有由 MahDouble 元素组成的列表才会获得 mahStuff 方法
val mahDoubleList: List[MahDouble] = List(2.0, 3.0, 4.0, 5.0)
此致,
亚历山德罗.
正如@Alessandro G. 建议的那样,最好的方法是为 MahDouble
创建特殊类型 - 而不是整个 List
:
case class MahDouble(d: Double) extends AnyVal
extends AnyVal
会给你 value class 以避免开销。
但是,我不建议您在 MahDouble
和 Double
之间进行隐式转换,因为它太不可预测并且非常难以理解正在发生的事情,请参阅 this article。
但是您仍然可以为您的特殊双打添加漂亮的构造函数:
implicit class RichDouble(d: Double){
def mah = MahDouble(d)
}
这是你的列表类型class:
implicit class RichMaxDoubleList(l: List[MahDouble]){
def mahStuff = "done"
}
现在您可以使用它了:
scala> val l = List(1.0 mah, 2.0 mah)
l: List[MahDouble] = List(MahDouble(1.0), MahDouble(2.0))
scala> l.mahStuff
res7: String = done
您也可以将常规列表转换为 mah 列表并返回:
scala> List(1.0, 2.0).map(_.mah)
res8: List[MahDouble] = List(MahDouble(1.0), MahDouble(2.0))
scala> res8.map(_.d)
res9: List[Double] = List(1.0, 2.0)
以下是我对隐式转换的看法。首先,隐式 class:
implicit class MahThing(val list: List[Double]) {
def mahStuff = {
// ...do your checks
this // to ensure we get the object back so I can chain list-like functions off it to prove it has been converted back.
}
}
和反向隐式 def 以转换回列表:
implicit def thing2list(thing: MahThing): List[Double] = thing.list
应用于双精度列表:
scala> dbs.mahStuff
res1: MahThing = MahThing@35e06c5d
scala> dbs.mahStuff.tail
res2: List[Double] = List(0.45)
对 tail 的调用表明 MahStuff 实例很容易转换回列表。
现在尝试使用字符串列表:
scala> val strs = "foo" :: "bar" :: Nil
strs: List[String] = List(foo, bar)
scala> strs.mahStuff
<console>:13: error: value mahStuff is not a member of List[String]
strs.mahStuff
^
显示其他列表类型未转换。
我想要一个在功能上扩展 List[Double]
并增加一些功能的自定义 class。我对 Pimp My Library 的理解会引导我构建如下内容:
implicit class MahThing(list:List[Double]) {
def mahStuff = ...
}
问题是,现在到处都导入 MahThing
,所有 List[Double]
都可以选择 mahStuff
。
同上:
class MahThing(list:List[Double]) {
def mahStuff ...
}
implicit def toThing(list:List[Double]) = new MahThing(list)
现在,list.toThing
生产 MahThing
,但 MahThing
不能做 List
y 东西。煞费苦心地将 MahThing
中的 List
操作定义为 list.operation
是很费力的。出于某种原因,使用 MahThing
的实例,它让我例如在 map
操作期间声明变量类型。
我真正需要的是扩展 List[Double]
的确切功能。本该 MahThing
的事情却 mahStuff
去做了,而没有其他人去做。另外,MahThing
在其他方面都和 List
一样。
使用隐式转换是扩展 List[T](在你的情况下 T 是 Double)功能的正确方法(作为 List[T] final,它不能被扩展)并且如你所见
everywhere MahThing is imported, all List[Double]s have the option to do mahStuff.
但是,如果我没弄错的话,你不希望所有的 List[Double] 都像那样,所以我的建议是创建一个 MahDouble class 来接受 Double 作为参数并将两种方式隐式转换为 Double
object MahDouble {
implicit def toMah(d: Double): MahDouble = new MahDouble(d)
implicit def backToDouble(m: MahDouble): Double = m.d
}
case class MahDouble(d: Double)
然后您可以将该 MahDouble 用作您的 MahThing List 的类型,并将其从 List[MahDouble] 隐式转换。
object MahThing {
implicit def toThing(list:List[MahDouble]): MahThing = new MahThing(list)
}
case class MahThing(list:List[MahDouble]) {
def mahStuff ...
}
对于任何 aspect MahDouble 都将作为 Double,但只有由 MahDouble 元素组成的列表才会获得 mahStuff 方法
val mahDoubleList: List[MahDouble] = List(2.0, 3.0, 4.0, 5.0)
此致, 亚历山德罗.
正如@Alessandro G. 建议的那样,最好的方法是为 MahDouble
创建特殊类型 - 而不是整个 List
:
case class MahDouble(d: Double) extends AnyVal
extends AnyVal
会给你 value class 以避免开销。
但是,我不建议您在 MahDouble
和 Double
之间进行隐式转换,因为它太不可预测并且非常难以理解正在发生的事情,请参阅 this article。
但是您仍然可以为您的特殊双打添加漂亮的构造函数:
implicit class RichDouble(d: Double){
def mah = MahDouble(d)
}
这是你的列表类型class:
implicit class RichMaxDoubleList(l: List[MahDouble]){
def mahStuff = "done"
}
现在您可以使用它了:
scala> val l = List(1.0 mah, 2.0 mah)
l: List[MahDouble] = List(MahDouble(1.0), MahDouble(2.0))
scala> l.mahStuff
res7: String = done
您也可以将常规列表转换为 mah 列表并返回:
scala> List(1.0, 2.0).map(_.mah)
res8: List[MahDouble] = List(MahDouble(1.0), MahDouble(2.0))
scala> res8.map(_.d)
res9: List[Double] = List(1.0, 2.0)
以下是我对隐式转换的看法。首先,隐式 class:
implicit class MahThing(val list: List[Double]) {
def mahStuff = {
// ...do your checks
this // to ensure we get the object back so I can chain list-like functions off it to prove it has been converted back.
}
}
和反向隐式 def 以转换回列表:
implicit def thing2list(thing: MahThing): List[Double] = thing.list
应用于双精度列表:
scala> dbs.mahStuff
res1: MahThing = MahThing@35e06c5d
scala> dbs.mahStuff.tail
res2: List[Double] = List(0.45)
对 tail 的调用表明 MahStuff 实例很容易转换回列表。
现在尝试使用字符串列表:
scala> val strs = "foo" :: "bar" :: Nil
strs: List[String] = List(foo, bar)
scala> strs.mahStuff
<console>:13: error: value mahStuff is not a member of List[String]
strs.mahStuff
^
显示其他列表类型未转换。