1. 實現一個Bug類,對沿着水平線爬行的蟲子建模。move方法向當前方向移動,turn方法讓蟲子轉身,show方法打印出當前的位置。讓這些方法能夠被串接調用。例如:java
bugsy.move(4).show().move(6).show().turn().move(5).show()算法
上述代碼應顯示 4 10 5。數組
package ex18_01 class Bug { var x = 0 var y = 0 var curr_direction = 0 def move(len: Int) = { curr_direction match { case 0 => x += len case 1 => y += len case 2 => x -= len case 3 => y -= len } this } def turn() = { curr_direction = (curr_direction + 1) % 4 this } def show() = { curr_direction match { case 0 => print(x + " ") case 1 => print(y + " ") case 2 => print(x + " ") case 3 => print(y + " ") } this } } object Main extends App { val bugsy = new Bug bugsy.move(4).show().move(6).show().turn().move(5).show() } /*output: 4 10 5 */
2. 爲前一個練習中的Bug類提供一個流利接口,達到能編寫以下代碼的效果:網絡
bugsy move 4 and show and then move 6 and show turn around move 5 and showide
解答://TODO函數
3. 完成18.1節中的流利接口,以便咱們能夠作出以下調用:this
book set Title to "Scala for the Impatient" set Author to "Cay Horstmann"spa
package ex18_03 object Main extends App { val book = new Document book set Title to "Scala for the Impatient" set Author to "Cay Horstmann" println(book) } // 知識點: 單例類型 object Title // This object is used as an argument for a fluent interface object Author class Document { private var title = "" private var author = "" private var useNextArgAs: Any = null def set(obj: Title.type): this.type = { useNextArgAs = obj; this } def set(obj: Author.type): this.type = { useNextArgAs = obj; this } def to(arg: String): this.type = { if (useNextArgAs == Title) title = arg if (useNextArgAs == Author) author = arg this } override def toString = getClass.getName + "[title=" + title + ", author=" + author + "]" } /*output: eg18_01_b.Document[title=Scala for the Impatient] */
4. 實現18.2節中被嵌套在Network類中的Member類的equals方法。兩個成員要想相等,必須屬於同一個網絡。scala
解答://TODOcode
5. 考慮以下類型別名
type NetworkMember = n.Member forSome { val n: Network }
和函數
def process(m1: NetworkMember, m2: NetworkMember) = (m1, m2)
這與18.8節中的process函數有什麼不一樣?
解答:該函數接受相同或不一樣網絡的成員,而18.8節中的process函數則拒絕那些來自不一樣網絡的成員。
package ex18_05 // 知識點: 存在類型 import javax.swing._ import scala.collection.mutable._ object Main extends App { type NetworkMember = n.Member forSome { val n: Network } def process(m1: NetworkMember, m2: NetworkMember) = (m1, m2) val chatter = new Network val myFace = new Network val fred = chatter.join("Fred") val wilma = chatter.join("Wilma") val barney = myFace.join("Barney") process(fred, wilma) // OK 接受相同網絡的成員 process(fred, barney) // OK 接受不一樣網絡的成員 fred.contacts += wilma // OK //fred.contacts += barney //ERROR } class Network { class Member(val name: String) { val contacts = new ArrayBuffer[Member] override def toString = getClass.getName + "[name=" + name + ",contacts=" + contacts.map(_.name).mkString("[", ",", "]") + "]" } private val members = new ArrayBuffer[Member] def join(name: String): Member = { val m = new Member(name) members += m m } override def toString = getClass.getName + "[members=" + members + "]" } /*output: */
6. Scala 類庫中的Either類型能夠被用於要麼返回結果,要麼返回某種失敗信息的算法。
編寫一個帶有兩個參數的函數:一個已排序整型數組和一個整數值。要麼返回該整數值在數組中的下標,要麼返回最接近該值的元素的下標。
使用一箇中置類型做爲返回類型。
package ex18_06 // 知識點: 中置類型 import scala.util.control.Breaks._ object Main extends App { def either(arr: Array[Int], value: Int) = { var re: (Int, Int) = (0, 0) if (value < arr(0)) re = arr(0) -> 0 else if (value > arr(arr.length - 1)) re = arr(arr.length - 1) -> (arr.length - 1) else { breakable { for (i <- 0 until arr.length) { if (arr(i) == value) { re = value -> i; break } else if (i < arr.length - 1 && arr(i) < value && value < arr(i + 1)) { if (value - arr(i) <= arr(i + 1) - value) { re = arr(i) -> i; break } else { re = arr(i + 1) -> (i + 1); break } } } } } re } val a = Array(1, 5, 6, 9) println(either(a, 1)) println(either(a, 5)) println(either(a, 6)) println(either(a, 9)) println(either(a, 0)) println(either(a, 7)) println(either(a, 8)) println(either(a, 10)) } /*output: (1,0) (5,1) (6,2) (9,3) (1,0) (6,2) (9,3) (9,3) */
7. 實現一個方法,接受任何具有以下方法的類的對象和一個處理該對象的函數。
調用該函數,並在完成或有任何異常發生時調用close方法。
package ex18_07 // 知識點: 結構類型 import scala.util.control.Breaks._ object Main extends App { def test(obj: { def close(): Unit }, f: { def close(): Unit } => Unit) = { try { f(obj) } catch { case ex: Exception => obj.close(); ex.printStackTrace() } finally { obj.close() } } }
8.
9.
10.