第二十章 抽象成員
package SecondWithProgrammingInScala
/**
* 抽象成員
* 不完全定義的類或者特質 ,包含val,var,def方法,type類型
*/
trait Abstract {
//類型成員 : 簡化類型參數 ,方便定義
type T
def transform(x: T): T
//表示確定的不會變化的值
val initial: T
//相當於生成了get/set方法
var current: T
}
//實現時候必須要對所有抽象的成員進行實現
class Concrete extends Abstract {
type T = String
override def transform(x: String): String = initial + x
override val initial: String = "hi"
override var current: String = initial
}
//val的初始化 ,如果成員變量是一個表達式 x+3 ,
//在IntTest初始化的時候不會計算表達式 ,initial會被默認爲0
trait IntTest {
val initial: Int
val time: Int
require(initial != 0)
def result = time * initial
}
//val的懶加載
object LazyDemo {
println("initial object")
val x = println("initial x")
lazy val y = println("initial y")
}
object AbstractApp {
def main(args: Array[String]): Unit = {
LazyDemo
println
LazyDemo.y
val num = 2
//預初始化
val test1 = new {
val initial = num + 3
} with IntTest {
val time = 2
def print = println(result)
}
test1.print
val testError = new IntTest {
val initial = num + 3
val time = 2
}
}
}
//合理利用抽象類型
trait Food {
def name: String
}
abstract class Animal {
def name: String
type SuitableFood <: Food
def eat(food: SuitableFood) = println(name + "吃" + food.name)
}
class Grass extends Food {
override def name: String = "草"
}
class Cow extends Animal {
override type SuitableFood = Grass
override def name: String = "牛"
}
object AbstractTypeApp {
def main(args: Array[String]): Unit = {
//將抽象類型放在子類中指定 ,更細緻的控制
val anima = new Cow
val food = new Grass
anima.eat(food)
}
}
//枚舉
object Color extends Enumeration {
val R = "red"
val G = "green"
val B = "blue"
}
第二十一章 隱式轉換和隱式參數
隱式轉換就像是自動的強制轉換類型 ,之前十九章的泛型中 ,一些類型限定/上下界限定/上下文限定等語法 ,其實就是爲了簡化隱式轉換 .
package SecondWithProgrammingInScala
import java.util.{Comparator, RandomAccess}
/**
* 隱式轉換和參數
*/
//對一些已有的無法改動的類(如庫函數/第三方庫) ,擴展自己定義的方法
//通過隱式轉換 ,將類A->類B ,類B是具有需要的方法的類
class A {
val name = "ClassA"
}
class B(val name: String) {
def print = println("hello " + name)
}
object Transform {
def main(args: Array[String]): Unit = {
//定義隱式轉換將A->B
/**
* 隱式轉換和使用對象需要在一個作用域
* 無歧義 ,同時只有一種隱式轉換可以調用
* 每次只調用一個隱式轉換 ,不能嵌套
* 優先執行顯示調用 ,只有無顯示方法纔會隱式轉換
*
* 類似Map(1->"A")中的->也是通過隱式轉化 ,轉化成Predef.ArrowAssoc ,並調用->方法
*/
implicit def wapper(a: A) = new B(a.name)
//使用a調用他並沒有的方法
val a = new A
a.print
//隱式轉換還可以通過參數列表傳入
def max1[T](a: T, b: T)(implicit cp: Comparator[T]) = {
if (cp.compare(a, b) >= 0) a else b
}
//聲明參數並引入
val cp = new Comparator[Int] {
override def compare(a: Int, b: Int) = a - b
}
println(max1(5, 6)(cp))
//直接聲明作用域變量
implicit val cp2 = new Comparator[Int] {
override def compare(a: Int, b: Int) = a - b
}
println(max1(5, 6))
}
}