我非常喜欢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!
没有定义每种货币的功能(欧元,美元,......)?
答案 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
特征的情况下实现,但是您可能会冒险添加货币而不为其添加转化。