說我寫的擴展方法隱含類應該總是擴展AnyVal嗎?
implicit class EnhancedFoo(foo: Foo) {
def bar() { /* ... */ }
}
如果你總是在類中包含defininition extends AnyVal
?在什麼情況下你不想讓一個隱式類成爲一個值類?
說我寫的擴展方法隱含類應該總是擴展AnyVal嗎?
implicit class EnhancedFoo(foo: Foo) {
def bar() { /* ... */ }
}
如果你總是在類中包含defininition extends AnyVal
?在什麼情況下你不想讓一個隱式類成爲一個值類?
讓我們來看看limitations listed for value classes並認爲當他們隱類可能不適合:
「必須只可以精確到一個公共的,VAL參數,其類型不是值類的主要構造。 「所以,如果你是包裝類本身就是一個值類,你不能使用implicit class
作爲一個包裝,但你可以這樣做:
// wrapped class
class Meters(val value: Int) extends AnyVal { ... }
// wrapper
class RichMeters(val value: Int) extends AnyVal { ... }
object RichMeters {
implicit def wrap(m: Meter) = new RichMeter(m.value)
}
如果包裝有隱含參數,以及,你可以嘗試將它們移動到方法聲明。即而不是
implicit class RichFoo[T](foo: Foo[T])(implicit ord: Ordering[T]) {
def bar(otherFoo: Foo[T]) = // something using ord
}
你有
implicit class RichFoo[T](foo: Foo[T]) extends AnyVal {
def bar(otherFoo: Foo[T])(implicit ord: Ordering[T]) = // something using ord
}
「可能沒有專門的類型參數。」你可能希望封裝器在封裝一個本身具有特定類型參數的類時專用。
equals
或hashCode
方法」。無關緊要,因爲隱式類也不應該有equals/hashCode
。var
或lazy val
的合理用例。 「另外,讓隱式類成爲一個值類可能會改變一些使用反射的代碼行爲,但反射通常不會看到隱式類。
如果你的隱式類確實滿足所有這些限制,我想不出一個理由不把它作爲一個值類。
我覺得你很困惑Value Classes與Implicit Classes。在爲增強定義隱式類時,您幾乎不會擴展任何內容,而值類必須擴展爲AnyVal
。
我可以把這個問題改爲「應該隱式類總是值類?」。如果它消除了實例創建的開銷,爲什麼你不希望隱式類是一個值類? – 2013-02-18 04:44:10
值類有很多限制。如果它們合適,當然可以使用它們進行增強。 – 2013-02-18 04:48:28
fwiw,下面是'隱式類'內的'lazy val'的用例:https://gist.github。com/SethTisue/8977033。幸運的是,有一個簡單的解決方法(也在要點中顯示)。 – 2014-02-13 15:28:39
「我想不出一個理由不讓它成爲價值課。」 - 因爲它分散注意力,但沒有任何好處。在我的測試中,我一直無法重現「擴展AnyVal」隱式類的所謂記憶好處。你有沒有提到好處? – Rich 2015-06-29 13:24:23
該文檔仍然推薦它,但我無法在測試中測量任何好處。 http://docs.scala-lang.org/overviews/core/value-classes.html – Rich 2015-06-29 13:49:36