快学Scala 第18章 高级类型 习题解答

1. 实现一个Bug类,对沿着水平线爬行的虫子建模。move方法向当前方向移动,turn方法让虫子转身,show方法打印出当前的位置。让这些方法可以被串接调用。例如:

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 show

解答://TODO

3. 完成18.1节中的流利接口,以便我们可以做出如下调用:

book set Title to "Scala for the Impatient" set Author to "Cay Horstmann"

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方法。两个成员要想相等,必须属于同一个网络。

解答://TODO

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.

7.

8.

9.

10.

时间: 2024-08-24 20:03:27

快学Scala 第18章 高级类型 习题解答的相关文章

快学Scala 第16章 XML处理 习题解答

1. <fred/>(0) 得到什么?<fred/>(0)(0)呢?为什么? 回答:<fred/>(0) 得到一个scala.xml.Node,<fred/>(0)(0)也是得到scala.xml.Node. 因为scala.xml.Node 实现了方法 def apply(i: Int): Node,所以支持串接调用. 注意:scala-xml-x.x.x.jar 需要另外导入. scala> val a = <fred/> a: sca

快学scala 第十一章 操作符 读书笔记及习题答案代码

chapter 11 操作符 标签:快学scala 一.笔记 scala种可以在反引号中包含几乎任何字符序列, val 'val' = 42 所有的操作符都是左结合的,除了以冒号(:)结尾的操作符,和赋值操作符.用于构造列表的::操作符是又结合的.1::2::Ni1的意思是1::(2::Ni1),先创建出包含2的列表,这个列表又被作为尾巴拼接到以1作为头部的列表中. 2. 函数调用语法:f(arg1, arg2,...)扩展到可以应用于函数之外的值,如果f不是函数或方法,那么这个表达式等于f.a

快学Scala第10章----特质

本章要点 类可以实现任意数量的特质 特质可以要求实现它们的类具备特定的字段.方法或超类 和Java接口不同,Scala特质可以提供方法和字段的实现 当你将多个特质叠加在一起时,顺序很重要--其方法先被执行的特质排在更后面 为什么没有多重继承 Scala和Java一样不允许类从多个超类继承:从多了超类继承可能会导致许多问题,例如两个超类有相同的方法,子类该如何使用和菱形继承.在java 中类只能扩展自一个超类,它可以实现任意数量的接口,但接口只能包含抽象方法,不能包含字段. Scala提供了特质(

快学Scala第13章----集合

本章要点 所有集合都扩展自Iterable特质 集合有三大类:序列.集.映射 对于几乎所有集合类,Scala都同时提供了可变的和不可变的版本 Scala列表要么是空的,要么拥有一头一尾,其中尾部本身又是一个列表 集是无先后次序的集合 用LinkedhashSet 来保留插入顺序,或者用SortedSet来按顺序进行迭代 '+' 将元素添加到无先后次序的集合中: +: 和 :+ 向前或向后追加到序列: ++将两个集合串接在一起: -和–移除元素 Iterable和Seq特质有数十个用于常见操作的方

快学Scala第14章----模式匹配和样例类

本章要点 match表达式是一个更好的switch,不会有意外掉入到下一个分支的问题. 如果没有模式能够匹配,会抛出MatchError.可以用case _ 模式来避免. 模式可以包含一个随意定义的条件,称作守卫. 你可以对表达式的类型进行匹配:优先选择模式匹配而不是isInstanceOf/asInstanceOf. 你可以匹配数组.元组和样例类的模式,然后将匹配到的不同部分绑定到变量. 在for表达式中,不能匹配的情况会被安静的跳过. 样例类继承层级中的公共超类应该是sealed的. 用Op

快学Scala第2章–控制结构和函数 笔记

条件表达式 在Scala中,if/else 表达式是有值的,这个就是跟在if或者else之后的表达式的值.例如: val s = if(x > 0) 1 else -1 // 类似于 var s = 0 if(x > 0) s = 1 else s = -1 Scala允许使用混合类型的返回值,例如: if(x > 0) "positive" else -1 上式表达式返回的类型是它们类型的公共超类型, 在这里java.lang.String 和 Int 它们的公共超

快学Scala 第13章 集合 - 练习解答

1. 编写一个函数,给定字符串,产出一个包含所有字符的下标的映射.举例来说:indexes("Mississippi")应返回一个映射,让'M'对应集{0},'i'对应集{1,4,7,10},依此类推. 使用字符到可变集的映射.另外,你如何保证集是经过排序的? 回答:使用SortedSet可以保证集是经过排序的. package ex13_01 import scala.collection.mutable.SortedSet import scala.collection.mutab

快学Scala 第十三课 (类型层级,对象相等性)

Scala 类型层级: 对象相等性: 和Java一样要重写equals方法和hashcode方法 class Student(val id: Int, val name: String) { override def equals(other: Any) = { val that = other.asInstanceOf[Student] if (that == null) false else id == that.id && name == that.name } override d

快学Scala 第17章 - 类型参数 习题解答

1. 定义一个不可变类Pair[T,S],带一个swap方法,返回组件交换过位置的新对偶. package ex17_01 object Main extends App {   val p = new Pair(97 -> 'a')   val a = p.swap   println(a) } class Pair[T, S](val p: (T, S)) {   def swap = {     (p._2, p._1)   } } /*output: (a,97) */ 2. 定义一个可