不完全定义的类或特质的成员为抽象成员。抽象成员将被声明类的子类实现。
四种抽象成员: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)
}
网友评论