快學Scala 第18章 高級類型 習題解答

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.

相關文章
相關標籤/搜索