《快學Scala》第17章習題參考解答(型別引數)
阿新 • • 發佈:2018-12-25
第一題
package p1{
class Pair[T, S](val first: T, val second: S){
def swap() = {
new Pair[S, T](second, first)
}
override def toString = "(" + first + ", " + second + ")"
}
object Main extends App{
val p1 = new Pair(13126, "xia")
val p2 = p1.swap
println(p2)
}
}
第二題
package p2{ class Pair[T](var first: T, var second: T){ def swap { val tmp = first first = second second = tmp } override def toString = "(" + first + ", " + second + ")" } object Main extends App{ val p1 = new Pair(13126, "xia") p1.swap println(p1) } }
第三題
package p3{ class Pair[T, S](val first: T, val second: S){ override def toString = "(" + first + ", " + second + ")" } object Main extends App{ def swap[T, S](p: Pair[T, S]) = { new Pair(p.second, p.first) } val p1 = new Pair(13126, "xia") println(swap(p1)) } }
第四題
package p4{ class Pair[T](val first: T, val second: T) { def replaceFirst(newFirst: T) = new Pair[T](newFirst, second) override def toString = "(" + first + ", " + second + ")" def replaceFirst2[R >: T](newFirst: R) = new Pair[R](newFirst, second) } class Person(val name: String, val age: Int){ override def toString = name + " " + age } class Student(val school: String, name: String, age: Int) extends Person(name, age){ override def toString = super.toString + " " + school } object Main extends App{ val p1 = new Pair(new Person("xia", 13126), new Person("zhang", 13126)) val p2 = p1.replaceFirst(new Student("nankai", "wang", 13126)) println(p2) // val p3 = new Pair(new Student("nankai", "xia", 13126), new Student("nankai", "zhang", 13126)) // val p4 = p3.replaceFirst(new Person("wang", 13126)) val p3 = new Pair(new Student("nankai", "xia", 13126), new Student("nankai", "zhang", 13126)) val p4 = p3.replaceFirst2(new Person("wang", 13126)) println(p4) } /* 1. Student是Person的子類,newfirst:Student可以轉化成Person(子->父) 2. p3, p4會導致編譯錯誤,這是是因為newFirst:Person無法轉化為Student(父->子) 3. replaceFirst2函式猶豫定義了新的型別變數下界,second:student轉化為Person(子->父) */ }
第五題
package p5{
/*
1. RichInt是為了豐富Int,而不是為了取代Int。
2. Int可以自動轉化為RichInt,一下來自Int的scaladoc
There is an implicit conversion from scala.Int => scala.runtime.RichInt which provides useful non-primitive operations.
3. 使用檢視定界可以將Comparable[Int]轉化為Comparable[RichInt]
*/
}
第六題
package p6{
object Main extends App{
def middle[T](lst: Iterable[T]): T = {
val l = lst.toList
l(lst.size / 2)
}
println(middle("World"))
}
}
第七題
package p7{
/*
- foldLeft:foldLeft[B](z: B)(op: (B, A) ⇒ B): B
- 在函式引數中(op: (B, A) ⇒ B為函式引數),型變是反轉過來的,所以此時
op函式引數的引數部分(B,A)是協變點。所以此時A是協變。
- 同樣的道理,grouped(size: Int): Iterator[Iterable[A]]
- foreach(f: (A) ⇒ Unit): Unit 都應該是協變點。
*/
}
第八題
package p8{
// class Pair[T](var first: T, var second: T){
// def replaceFirst[R >: T](newFirst: R) {first = newFirst}
// }
/*
- 由於Pair沒有型變,所以Pair[T]和Pair[R]沒有任何關係。Pair[T]無法變成Pair[R],
若要完成上述轉變,需要Pair[T]是Pair[R]的子類,需要對Pair使用協變。
*/
}
第九題
package p9{
import scala.math._
// 此處T為協變,而函式repalceFirst中T為逆變點。
class Pair[+T](val first: T, val second: T){
// T is a covariance type. So an invariance R is introduced.
def replaceFirst[R >: T](newFirst: R) = {
new Pair(newFirst, second)
}
override def toString = "(" + first + ", " + second + ")"
}
class NastyDoublePair(first: Double, second: Double) extends Pair[Double](first, second){
override def replaceFirst[R >: Double](newFirst: R) = {
new Pair(newFirst, second)
}
}
object Main extends App{
// T為逆變,Pair[Any]是Pair[Double]的子類,Pair[Double]無法轉化為Pair[Any]
// val p: Pair[Any] = new NastyDoublePair(10, 20)
val p: Pair[Double] = new NastyDoublePair(10, 20)
//函式需要Double或者其父類。而String不是Double的父類。
// println(p.replaceFirst("Hello"))
println(p.replaceFirst(10))
}
}
第十題
package p10{
class Pair[S, T](var first: S, var second: T){
def swap(implicit ev1: T =:= S, ev2: S =:= T){
var tmp = first
first = second
second = tmp
}
override def toString = "(" + first + ", " + second + ")"
}
object Main extends App{
val p1 = new Pair(10, 11)
p1.swap
println(p1)
// val p2 = new Pair(10, "Hello")
// println(p2.swap)
}