1. 程式人生 > >《快學Scala》第17章習題參考解答(型別引數)

《快學Scala》第17章習題參考解答(型別引數)

第一題

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)	
}