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

1. 实现一个Bug类,对沿着水平线爬行的虫子建模。move方法向当前方向移动,turn方法让虫子转身,show方法打印出当前的位置。让这些方法可以被串接调用。例如
bugsy.move(4).show().move(6).show().turn().move(5).show()
  
  
object Scala18 { def main(args: Array[String]): Unit = { val bugsy = new Bug bugsy.move(4).show().move(6).show().turn().move(5).show() } } class Bug { var location = 0 var current = 0 def move(len: Int): this.type = { if (current == 0) location += len else location -= len this } def show(): this.type = { println("location=" + location) this } def turn(): this.type = { current = if (current == 0) 1 else 0 this } }

2. 为前一个练习中的Bug类提供一个流利接口,达到能编写如下代码的效果:
bugsy move 4 and show and then move 6 and show turn around move 5 and show
  
  
object Scala18 { def main(args: Array[String]): Unit = { val bugsy = new Bug bugsy move 4 and Show and Then move 6 and Show turn Around move 5 and Show } } trait BugType object Show extends BugType object Then extends BugType object Around extends BugType class Bug { var location = 0 var current = 0 def and(bugType: BugType): this.type = { if (bugType.isInstanceOf[Show.type]) show() this } def move(len: Int): this.type = { if (current == 0) location += len else location -= len this } def show(): this.type = { println("location=" + location) this } def turn(bugType: BugType): this.type = { current = if (current == 0) 1 else 0 this } }

3. 完成18.1节中的流利接口,以便我们可以做出如下调用:
book set Title to"Scala for the Impatient" set Author to "Cay Horstmann"
  
  
object Scala18 { def main(args: Array[String]): Unit = { val book = new Book println(book set Title to "Scala for the Impatient" set Author to "Cay Horstmann") } } trait BookType object Title extends BookType object Author extends BookType class Book { private var bookType: BookType = _ private var title: String = _ private var author: String = _ def set(bookType: BookType): Book = { this.bookType = bookType this } def to(str: String): Book = { bookType match { case _: Title.type => title = str case _: Author.type => author = str case _ => } this } override def toString: String = { "Book title=" + title + " author=" + author } }

4. 实现18.2节中被嵌套在Network类中的Member类的equals方法。两个成员要想相等,必须属于同一个网络。
  
  
object NetWork { def main(args: Array[String]): Unit = { val chatter = new NetWork val myFace = new NetWork val fred = chatter.join("Fred") val whe = chatter.join("Whe") val barney = myFace.join("Barney") fred.contacts += barney println(fred.equals(whe)) } } class NetWork { netWork => class Member(val name: String) { val contacts = new ArrayBuffer[NetWork#Member] override def equals(obj: scala.Any): Boolean = { obj match { case _: Member => true case _ => false } } } private val members = new ArrayBuffer[Member] def join(name: String): Member = { val m = new Member(name) members += m m } }
5. 考虑如下类型别名
type NetworkMember = n.Member forSome { val n: Network }
和函数
def process(m1: NetworkMember, m2: NetworkMember) = (m1, m2)
这与18.8节中的process函数有什么不同?
  
  
class Network { class Member(val name: String) { val contacts = new ArrayBuffer[Member] } private val members = new ArrayBuffer[Member] def join(name: String) = { val m = new Member(name) members += m m } } 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 barney = myFace.join("Barney") var jiexray = chatter.join("jiexray") process(fred, barney) process(fred, jiexray) }
6. Scala 类库中的Either类型可以被用于要么返回结果,要么返回某种失败信息的算法。编写一个带有两个参数的函数:一个已排序整型数组和一个整数值。要么返回该整数值在数组中的下标,要么返回最接近该值的元素的下标。使用一个中置类型作为返回类型
  
  
def main(args: Array[String]): Unit = { val intOrInt = find(Array(2, 3, 4, 12121, 322, 1122, 34, 11), 1000) println(intOrInt) } def find(arr: Array[Int], num: Int): Int Either Int = { var approach = 0 var approachIndex = 0 for (i <- arr.indices) { if (arr(i) == num) { Right(i) } else if (Math.abs(arr(i) - num) < Math.abs(approach - num)) { approach = arr(i) approachIndex = i } } Left(approachIndex) }
7. 实现一个方法,接受任何具备如下方法的类的对象和一个处理该对象的函数。调用该函数,并在完成或有任何异常发生时调用close方法。
  
  
object Practice { def main(args: Array[String]): Unit = { val target = new Target practice7(target, fun) } def practice7[T <: {def close() : Unit}](target: T, fun: (T) => Unit): Unit = { try { fun(target) } finally { target.close() } } def fun(target: {def close(): Unit}) { println("target") } } class Target { def close(): Unit = { println("close") } }
8. 编写一个函数printValues,带有三个参数f、from和to,打印出所有给定区间范围内的输入值经过f计算后的结果。这里的f应该是任何带有接受Int产出Int的apply方法的对象。例如:
printValues((x: Int) => x*x, 3, 6) //将打印 9 16 25 36printValues(Array(1, 1, 2, 3, 5, 8, 13, 21, 34, 55), 3, 6) //将打印 3 5 8 13
  
  
object Practice { def main(args: Array[String]): Unit = { printValues(Test, 3, 6) printValues(Array(1, 1, 2, 3, 5, 8, 13, 21, 34, 55), 3, 6) } def printValues(f: {def apply(int: Int): Int}, from: Int, to: Int): Unit = { for (i <- from to `to`) print(f(i) + "\t") println() }
  
  
}
  
  
object Test { def apply(int: Int): Int = { int * int } }
9. 考虑如下对物理度量建模的类:
  
  
abstract class Dim[T](val value: Double, val name: String) { protected def create(v: Double): T def +(other: Dim[T]): T = create(value + other.value) override def toString(): String = value + "" + name }
以下是具体子类:
  
  
class Seconds(v: Double) extends Dim[Seconds](v, "s") { override def create(v: Double) = new Seconds(v) }
但现在不清楚状况的人可能会定义
  
  
class Meters(v: Double) extends Dim[Seconds](v, "m") { override def create(v: Double) = new Seconds(v) }
允许米(Meters)和秒(Seconds)相加。使用自身类型来防止发生这样的情况。
  
  
abstract class Dim[T](val value: Double, val name: String){ this: T => protected def create(v: Double): T def + (other: Dim[T]) = create(value + other.value) override def toString() = value + " " + name } class Seconds(v: Double) extends Dim[Seconds](v, "s"){ override def create(v: Double) = new Seconds(v) } class Meters(v: Double) extends Dim[Meters](v, "m"){ override def create(v: Double) = new Meters(v) }
10. 自身类型通常可以被扩展自身的特质替代,但某些情况下使用自身类型会改变初始化和重写的顺序。构造出这样的一个示例。
  
  
trait A { def sing() = "from a" } trait C { this: A => val w = sing + "from c" } class B{ this: C => val k = w } val b = new B with C with A println(b.k)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值