`
mwei
  • 浏览: 124179 次
  • 性别: Icon_minigender_1
  • 来自: 抽象空间
社区版块
存档分类
最新评论

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





分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics