Scala:抽象成员之汇率代码的整理

对Prgramming in Scala 2nd的第20章“汇率”的例子进行了整理,添加了部分注释。
只能说:抽象类型很好很强大!

/**
* 通过抽象类型的延迟实现,达到一种安全的类型操作
*/
object TestCurrency extends Application{ //客户端代码入口
val ret1=Japan.Yen from US.Dollar * 100
val ret2=Europe.Euro from ret1
val ret3=US.Dollar from ret2

println(ret1) //12110 JPY
println(ret2) //75.95 EUR
println(ret3) //99.95 USD 转换之后基本等同于原来的100USD,毕竟转换关系并不精确
println(US.Dollar*100+ret3) //199.95 USD
//println(US.Dollar+Europe.Euro) //good!!compile error: type mismatch; this is what we want
println(US.Dollar*100) //100.00 USD
println(Japan.Yen*100) //100 JPY
}

abstract class CurrencyZone{
type Currency <: AbstractCurrency //定义汇率类型上界
val CurrencyUnit:Currency //汇率单位
def make(x:Long):Currency //工厂方法,其实现推迟到具体子类

abstract class AbstractCurrency{ //抽象内部类
val amount:Long //数量 -抽象的
def designation:String //汇率名称 -抽象的
def +(that:Currency):Currency=make(this.amount+that.amount)
def -(that:Currency):Currency=make(this.amount-that.amount)
def *(x:Double):Currency=make((this.amount*x).toLong)
def /(that:Double)=make((this.amount/that).toLong)
def /(that:Currency)=this.amount.toDouble/that.amount
//from:从other转到当前(调用方)汇率
def from(other:CurrencyZone#AbstractCurrency):Currency= //路径依赖类型:CurrencyZone#AbstractCurrency
make(math.round(
other.amount.toDouble*Converter.exchangeRate(other.designation)(this.designation)))
//10^x ~= n , 返回x
private def decimals(n:Long):Int=
if(n==1) 0 else 1+decimals(n/10)
//重写:formatted的作用是根据单位来决定小数点后的位数
override def toString=((amount.toDouble/CurrencyUnit.amount)
formatted ("%."+ this.decimals(CurrencyUnit.amount)+"f")+" "+this.designation)
}
}

object US extends CurrencyZone{
abstract class Dollar extends AbstractCurrency{
def designation="USD" //抽象的designation在此实现
}
type Currency=Dollar //类型延迟实现,可避免不同币种的直接运算
def make(cent:Long)=new Dollar{
val amount=cent //抽象的amount在此实现
}
val Cent=make(1)
val Dollar=make(100)
val CurrencyUnit=Dollar
}

object Europe extends CurrencyZone{ //同US单例
abstract class Euro extends AbstractCurrency{
def designation="EUR"
}
type Currency=Euro
def make(cents:Long)=new Euro{ val amount=cents }
val Cent=make(1)
val Euro=make(100)
val CurrencyUnit=Euro
}

object Japan extends CurrencyZone{ //同US单例
abstract class Yen extends AbstractCurrency{
def designation="JPY"
}
type Currency=Yen
def make(yen:Long)=new Yen{val amount=yen}
val Yen=make(1) //日圆的的最小单位,没有日分
val CurrencyUnit=Yen
}

object Converter{ //不同汇率间的转换关系(这个数据结构不错:)
var exchangeRate =
Map(
"USD" -> Map("USD" -> 1.0 , "EUR" -> 0.7596,
"JPY" -> 1.211 , "CHF" -> 1.223),
"EUR" -> Map("USD" -> 1.316 , "EUR" -> 1.0 ,
"JPY" -> 1.594 , "CHF" -> 1.623),
"JPY" -> Map("USD" -> 0.8257, "EUR" -> 0.6272,
"JPY" -> 1.0 , "CHF" -> 1.018),
"CHF" -> Map("USD" -> 0.8108, "EUR" -> 0.6160,
"JPY" -> 0.982 , "CHF" -> 1.0 )
)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值