scala用户定义了带有implicits的文字

时间:2013-11-20 19:02:30

标签: scala literals implicits

我非常喜欢Scala的灵活性和简洁性。有了金额的定义:

case class MoneyAmount(amount: Double, currency: Currency)

trait Currency
case object EUR extends Currency
case object USD extends Currency

您可以轻松创建实例:

val m1 = MoneyAmount(100, EUR)

在范围内使用以下定义更容易:

implicit class DoubleMoney(amount: Double) {
  def apply(currency: Currency) = MoneyAmount(amount, currency)
}

val m2 = 100 (EUR)
val m3 = 100 (USD)

我的问题是:有没有办法可以实现以下目标:

val m3 = 100 EUR // does not compile!

没有定义每种货币的功能(欧元,美元,......)?

1 个答案:

答案 0 :(得分:0)

正如我上面所评论的,我不相信如果不将货币定义为方法就可以做到这一点。但是,您也可以使用方法来定义Currency对象。然后可以在特征中定义这些方法,以确保货币及其转换保持一致。

这是一个小工作表示例:

object Money {
  import scala.math.BigDecimal

  /** Wrap a BigDecimal with a Currency - doubles and money do not play nicely */
  case class MoneyAmount(amount: BigDecimal, currency: Currencies.Type) {
    override def toString: String = s"${amount} ${currency.symbol}"
  }

  /** Trait that lists all the available currencies */
  trait Currencies {
    /** Abstract type provided by the implementations */
    type Type

    def EUR: Type
    def USD: Type
  }

  /** Object that holds all the available currencies as case class objects */
  object Currencies extends Currencies {
    case class Type(symbol: String, decimalPlaces: Int)

    override val EUR = Type("EUR", 2)
    override val USD = Type("USD", 2)
  }

  /** Implicit conversion from Int to money about */
  implicit class IntToMoneyAmount(value: Int) {
    type Type = MoneyAmount

    private def makeAmount(currency: Currencies.Type) = MoneyAmount(BigDecimal(value), currency)

    override def EUR = makeAmount(Currencies.EUR)
    override def USD = makeAmount(Currencies.USD)
  }

  5 EUR                                           //> res0: Money.MoneyAmount = 5 EUR
}

这非常详细,可以在没有Currency特征的情况下实现,但是您可能会冒险添加货币而不为其添加转化。