Scala 如何扩展列表[双精度]
我想要一个自定义类,它在功能上扩展了Scala 如何扩展列表[双精度],scala,implicit-conversion,implicit,Scala,Implicit Conversion,Implicit,我想要一个自定义类,它在功能上扩展了List[Double],并添加了一些功能。我对《拉皮条客我的图书馆》的理解将引导我构建如下内容: implicit class MahThing(list:List[Double]) { def mahStuff = ... } 问题是,现在只要导入MahThing,所有List[Double]s都可以选择执行MahThing 同: class MahThing(list:List[Double]) { def mahStuff ... }
List[Double]
,并添加了一些功能。我对《拉皮条客我的图书馆》的理解将引导我构建如下内容:
implicit class MahThing(list:List[Double]) {
def mahStuff = ...
}
问题是,现在只要导入MahThing
,所有List[Double]
s都可以选择执行MahThing
同:
class MahThing(list:List[Double]) {
def mahStuff ...
}
implicit def toThing(list:List[Double]) = new MahThing(list)
现在,list.toThing
产生mahting
,但是mahting
不能做list
y的东西。在mahting
中将List
操作定义为List是很费劲的。操作
是很费劲的。出于某种原因,在使用mahting
的实例时,我会在map
操作期间声明变量类型
我真正需要的是扩展
List[Double]
的确切功能。本来应该是MahThing
的事情可以去做MahThing
,而没有其他人去做。PlusMahThing
在其他各方面都像一个List
。使用隐式转换是扩展List[T](在您的例子中,T是双倍)功能(作为List[T]final,不能扩展)的正确方法,正如您所看到的
无论何时导入MahThing,所有列表[Double]都可以选择
做点什么
但是,如果我没有弄错的话,您不希望所有的List[Double]都是这样的,所以我的建议是创建一个MahDouble类,它将接受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)
然后,您可以将该mahdool用作mahting列表的类型,并隐式地从List[mahdool]转换它
object MahThing {
implicit def toThing(list:List[MahDouble]): MahThing = new MahThing(list)
}
case class MahThing(list:List[MahDouble]) {
def mahStuff ...
}
对于任何方面,Mahdool都将起作用并成为Double,但只有由Mahdool元素组成的列表才能获得mahStuff方法
val mahDoubleList: List[MahDouble] = List(2.0, 3.0, 4.0, 5.0)
问候,,
Alessandro.正如@Alessandro G.所建议的,最好的方法是为
Mahdool
创建特殊类型-而不是整个列表
:
case class MahDouble(d: Double) extends AnyVal
扩展AnyVal
可以避免开销
但是,我不建议您在MahDouble
和Double
之间进行隐式转换,因为这太不可预测,而且很难理解发生了什么,请参阅
但你仍然可以为你的特殊双打添加漂亮的构造器:
implicit class RichDouble(d: Double){
def mah = MahDouble(d)
}
下面是列表的类型类:
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列表,也可以转换为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)
以下是我如何看待隐式转换的工作方式。首先,隐式类:
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
^
scala>val strs=“foo”::“bar”::无
strs:List[String]=List(foo,bar)
scala>strs.mahStuff
:13:错误:值不是列表[字符串]的成员
沙丁鱼
^
显示其他列表类型未转换。您可以添加另一个隐式转换-从
MahThing
到list[Double]
您实际想做什么?列表
是mahting
的实现细节吗?您是否希望list
是可变的,这样做mahting.list.somemutatinglist操作(…)
是不可行的?@BrianKent,我想做mahtuff
!主要是对清单做出保证。。。断言属性。。。诸如此类。为了扩展这句话,MahThing
是一个列表,只是一个包含附加功能的列表。@Shadowlands你能把它写下来作为一个答案,表明它做了我想要的吗?如上所述,我在导入隐式类mahtool
的任何地方都会遇到问题,因为我将mahtool
提供给所有List
s。mahtool
可能是一个值类:case类mahtool(d:Double)扩展了AnyVal
。我不建议在Double
和mahDouble
之间进行隐式转换-这太不可预测了(请参阅JavaConvertions vs JavaConverters主题以获取论证)。最好的方法是隐式添加clear方法:val mahDoubleList=List(2.0.mah,3.0.mah,4.0.mah,5.0.mah)
,您可以在这里摆脱显式类型,顺便说一句。@dk14获得了它,很高兴知道我可以这样做。谢谢:)@AlessandroG。谢谢你对这方面的见解。用def mahStuff=println(“sup”)
粘贴你写的所有东西,我无法mahStuff.mahStuff
。想什么?@WalrustheCat欢迎你。您是否碰巧遇到了类似“value mahStuff不是列表[MahDouble]的成员”这样的错误?如果是这样的话,记得在需要使用的地方添加import MahThingMahThing@AlessandroG. 一定是这样,一切似乎都正常运转。谢谢。很酷,但是所有的List[Double]
s都被转换了吗?是的,只要-对于该列表-隐式转换是嘿,我很感谢你对这一点的理解,但它并不是在功能上扩展List[Double]。考虑到上面的代码:List(1.0)map{{{uu.mah}map{{uu+1}
@mahdoole可以是一个函子,如果您需要对其进行变异,只需添加映射操作(基于复制方法),或者只需使用“map{.d+1}map{.mah}”。除包装或包装外的其他解决方案通常不安全。