【2019-06-04】scala抽象成员

不完全定义的类或特质的成员为抽象成员。抽象成员将被声明类的子类实现。
四种抽象成员:val、var、方法及类型

抽象类型val
定义形式:

//指定了val的名称和类型,不指定值。
val initial:String
//值必须由子类的具体val定义提供
 class Concrete extends Abstract {
    type T = String
    def transform(x: String) = x + x
    val initial = "hi"
    var current = initial
  }
//抽象的val声明类似于抽象的无参数方法声明
def initial:String

抽象的val限制了合法的实现方法:任何实现都必须是val类型的定义,不可以是var或def。

//重写的抽象val及无参数方法
object DefOverVal {
  abstract class Fruit {
    val v: String // `v' for value
    def m: String // `m' for method
  }
  
  abstract class Apple extends Fruit {
    val v: String
    val m: String // 可以用val重写def
  }
  
  abstract class BadApple extends Fruit {
    def v: String // 错误:不能用def重写val
    def m: String
  }
}

抽象var

object AbstractTime {
//只声明名称和类型,没有初始值。
  trait AbstractTime1 {
    var hour: Int
    var minute: Int
  }

//抽象var扩展为getter和setter方法
  trait AbstractTime2 {
    def hour: Int          // getter for `hour'
    def hour_=(x: Int)     // setter for `hour'
    def minute: Int        // getter for `minute'
    def minute_=(x: Int)   // setter for `minute'
  }


  // these traits combine with no conflict
  class AbstractTime extends AbstractTime1 with AbstractTime2 {
    var hour: Int = 10
    var minute: Int = 10
  }
}

初始化抽象val

object Misc {
  object Obj1 {
//参数化特质的方式就是通过需要在子类中实现的抽象val完成
    trait RationalTrait { 
      val numerArg: Int 
      val denomArg: Int 
    } 
//实例化特质,实现抽象的val定义
    new RationalTrait {
      val numerArg = 1
      val denomArg = 2
    }

    val expr1 = 1
    val expr2 = 2
//expr1、expr2作为匿名类初始化的一部分计算,匿名类的初始化在RationalTrait之后
    new RationalTrait {
      val numerArg = expr1
      val denomArg = expr2
    }

//枚举类型
    object Color extends Enumeration {
      val Red = Value
      val Green = Value
      val Blue = Value
    }

    import Color._
    val color1 = Red

    object Direction extends Enumeration {
      val North, East, South, West = Value
    }

 //创建具体的货币值
    new Currency {
      val amount = 79L
      def designation = "USD"
    }
//对美元和欧元建模为货币类的两个子类
    abstract class Dollar extends Currency {
      def designation = "USD"
    }
    abstract class Euro extends Currency {
      def designation = "Euro"
    }

    abstract class CurrencyZone {
      type Currency <: AbstractCurrency
      def make(x: Long): Currency
      abstract class AbstractCurrency {
        val amount: Long
        def designation: String 
        def + (that: Currency): Currency = 
          make(this.amount + that.amount)
        def * (x: Double): Currency = 
          make((this.amount * x).toLong)
      }
    }

    object US extends CurrencyZone {
      abstract class Dollar extends AbstractCurrency {
        def designation = "USD"
      }
      type Currency = Dollar
      def make(x: Long) = new Dollar { val amount = x }
    }
  }

  object Obj2 {
//使用了抽象val的特质
    trait RationalTrait { 
      val numerArg: Int 
      val denomArg: Int 
      require(denomArg != 0)
      private val g = gcd(numerArg, denomArg)
      val numer = numerArg / g
      val denom = denomArg / g
      private def gcd(a: Int, b: Int): Int = 
        if (b == 0) a else gcd(b, a % b)
      override def toString = numer +"/"+ denom
    }
//对象定义中的预初始化字段
    object twoThirds extends {
      val numerArg = 2
      val denomArg = 3
    } with RationalTrait
//类定义中的预初始化字段
    class RationalClass(n: Int, d: Int) extends {
      val numerArg = n
      val denomArg = d
    } with RationalTrait {
      def + (that: RationalClass) = new RationalClass(
        numer * that.denom + that.numer * denom,
        denom * that.denom
      )
    }

    object Color extends Enumeration {
      val Red, Green, Blue = Value
    }

    abstract class CurrencyZone {
    
      type Currency <: AbstractCurrency
      def make(x: Long): Currency
    
      abstract class AbstractCurrency {
        val amount: Long
        def designation: String 
    
        def + (that: Currency): Currency = 
          make(this.amount + that.amount)
        def * (x: Double): Currency = 
          make((this.amount * x).toLong)
        def - (that: Currency): Currency = 
          make(this.amount - that.amount)
        def / (that: Double) = 
          make((this.amount / that).toLong)
        def / (that: Currency) = 
          this.amount.toDouble / that.amount
    
        def from(other: CurrencyZone#AbstractCurrency): Currency = 
          make(Math.round(
            other.amount.toDouble * Converter.exchangeRate
              (other.designation)(this.designation)))
    
        private def decimals(n: Long): Int = 
          if (n == 1) 0 else 1 + decimals(n / 10)
    
        override def toString = 
          ((amount.toDouble / CurrencyUnit.amount.toDouble)
           formatted ("%."+ decimals(CurrencyUnit.amount) +"f")
           +" "+ designation)
      }
    
      val CurrencyUnit: Currency
    }

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

  class Outer {
    class Inner
  }
}

抽象类型

object Animals {
//用抽象类型建模合适的食物
  class Food
  abstract class Animal {
    type SuitableFood <: Food
    def eat(food: SuitableFood)
  }

  class Grass extends Food
//在子类中实现抽象类型
  class Cow extends Animal {
    type SuitableFood = Grass
    override def eat(food: Grass) {}
  }

}

路径依赖类型

//不同的路径产生不同类型
 class DogFood extends Food
  class Dog extends Animal {
    type SuitableFood = DogFood
    override def eat(food: DogFood) {}
  }

懒加载val

//让系统本身管理初始化的顺序
//通过懒加载 val初始化特征
 trait LazyRationalTrait { 
    val numerArg: Int 
    val denomArg: Int 
    lazy val numer = numerArg / g
    lazy val denom = denomArg / g
    override def toString = numer +"/"+ denom
    private lazy val g = {
      require(denomArg != 0)
      gcd(numerArg, denomArg)
    }
    private def gcd(a: Int, b: Int): Int = 
      if (b == 0) a else gcd(b, a % b)
  }

你可能感兴趣的:(【2019-06-04】scala抽象成员)