2015-09-02 124 views
1

我想要一個自定義類,功能上延伸List[Double],並增加了一些功能。我皮條客我的理解圖書館將導致我構建這樣的事情:如何擴展列表[雙]

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ÿ東西。辛苦地定義List作業MahThing作爲list.operation是辛苦的。出於某種原因,與MahThing的實例一起工作,它使我例如在map操作中聲明變量類型。

我真正需要的是擴展List[Double]的確切功能。應該是MahThing的事情可以做mahStuff,沒有其他人做。 Plus MahThing在所有其他方面的行爲就像List一樣。

+3

你可以添加另一個隱式轉換 - 從'MahThing'到'List [Double]' – Shadowlands

+0

你究竟在做什麼? 'list'是'MahThing'的實現細節嗎?你打算'list'是可變的,這樣'mahThing.list.someMutatingListOperation(...)'是不可行的嗎? –

+0

@BrianKent,我想做'mahStuff'!主要是保證有關列表...斷言屬性... whatnot。爲了*擴展*該語句,'MahThing' *是一個'List',只是一個包含附加功能的列表。 –

回答

2

使用隱式轉換是延長一個List [T](T是雙重你的情況)的功能(即列表[T]最後它不能擴展),以正確的方式,當你看到

無處不在MahThing是進口的,所有列表[Double] s都可以選擇 do mahStuff。

但是,如果我這樣做是正確,你不希望所有列表[雙] S是那樣的,所以我的建議是建立一個MahDouble類,將接受雙重的參數和隱式轉換左右逢源到雙

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列表和隱式地從列表[MahDouble]轉換。製成MahDouble元件

object MahThing { 
    implicit def toThing(list:List[MahDouble]): MahThing = new MahThing(list) 
} 

case class MahThing(list:List[MahDouble]) { 
    def mahStuff ... 
} 

對於任何方面MahDouble將作用和是雙的,但只列出將獲得mahStuff方法

val mahDoubleList: List[MahDouble] = List(2.0, 3.0, 4.0, 5.0) 

問候, 的Alessandro。

+2

'MahDouble'可以是一個值類:'case class MahDouble(d:Double)extends AnyVal'。我不建議'Double'和'mahDouble'之間的隱式轉換 - 它太不可預知(請參閱JavaConvertions與JavaConverters主題進行論證)。最好的方法是隱式添加清除方法:'val mahDoubleList = List(2.0.mah,3.0.mah,4.0.mah,5.0.mah)',你可以在這裏擺脫顯式類型,順便說一句。 – dk14

+0

@ dk14得到它,很高興知道我可以這樣做。謝謝:) –

+0

@AlessandroG。感謝您對此的洞察。用'def mahStuff = println(「sup」)粘貼你寫的所有內容''我無法'mahDoubleList.mahStuff'。思考? –

1

由於@Alessandro G.建議最好的辦法是爲MahDouble創建特殊類型 - 不是整個List

case class MahDouble(d: Double) extends AnyVal 

extends AnyVal會給你value class避免開銷。

但是,我不建議您在MahDoubleDouble之間進行隱式轉換,因爲它太不可預知,並且極難理解發生了什麼,請參閱this article

但你仍然可以添加漂亮的構造爲您的特殊雙打:

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 

您可以將常規列表轉換爲麻將列表,並返回:

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) 
+0

嘿,我很欣賞你對此的洞察,但它並沒有在功能上擴展List [Double]。根據上面的代碼,這將不起作用:'List(1.0)map {_.mah} map {_ + 1}' –

+0

@MahDouble可能是一個仿函數,如果您需要修改它 - 只需添加映射操作(基於複製方法),或者只使用'map {_.d + 1} map {_.mah}'。除包裝或[斯卡拉斯幻影類型](http://eed3si9n.com/learning-scalaz/Tagged+type.htm)以外的其他解決方案通常都不安全。 – dk14

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. 
    } 
} 

和反向隱含的高清轉換回列表:

implicit def thing2list(thing: MahThing): List[Double] = thing.list 

適用於雙列表:

scala> dbs.mahStuff 
res1: MahThing = [email protected] 

scala> dbs.mahStuff.tail 
res2: List[Double] = List(0.45) 

尾調用顯示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 
       ^

顯示,其他列表類型不會被轉換。

+0

酷,但所有的'列表[雙]'轉換? –

+0

是的,只要 - 對於該列表 - 隱式轉換[範圍](https://www.artima.com/pins1ed/implicit-conversions-and-parameters.html) – Shadowlands