LL脳がscalaの勉強を始めたよ その71


なかなか進まないScalaコップ本の19章をやっていきますよー、今回は以前に作成したQueueクラスをベースに下限境界についてやりますねー

とりあえず待ち行列クラスQueueはこんな感じでしたな、時間があいてしまったので…少し忘れ気味デス(´・ω・`)

// 外部からアクセスすための公開インターフェースとしてのトレイト
trait Queue[T]{
  def head:T
  def tail:Queue[T]
  def append(x:T):Queue[T]
}

// クラス実装自体を格納するオブジェクトです
object Queue{
  // 待ち行列クラスの実装を行う非公開クラスです
  // 実装内容はこれまでのQueueと同じですネ
  private class QueueImpl[T](
    private val leading:List[T],
    private val trailing:List[T]
    // トレイトミックスインです
    ) extends Queue[T]{
      def mirror = {
        if(leading.isEmpty) new QueueImpl(trailing.reverse, Nil)
        else this
      }
      def head:T = mirror.leading.head
      def tail:QueueImpl[T] = {
        val q = mirror
        new QueueImpl(q.leading.tail, q.trailing)
      }
      def append(x:T) = new QueueImpl(leading, x::trailing)
    }
  // オブジェクト生成用のapplyメソッドデス
  def apply[T](xs:T*):Queue[T] = new QueueImpl[T](xs.toList, Nil)
}

下限境界

上で作成したQueue[T]の定義ではTがappendメソッドの中で現れるものの、Tが出てくる位置は陰性ポジションらしいのでTは共変にできないらしいです。なぜか?はいまいちわからんのですが…

ただしappendメソッドを多相的(appendメソッド自体に型パラメータを与える)にして、その型パラメータに下限境界を設定するとうまい具合にいくらしいです…という呪文のような説明だけだとさっぱりなので、サンプル見てみますかね

実際にはappendに型パラメータUを与えると同時にU >: Tという境界設定構文を使うみたいですね

class Queue[+T](private val leading:List[T], private val trailing:List[T]{
  // 下限境界を設定しますよ
  def append[U >: T](x:U) = new Queue[U](leading, x::trailing)//...
}

ちなみにU :> T構文を使うためにはUはTのスーパークラスである必要があるとか…なので結果的にQueue[T]はQueue[U]という結果型になるっぽいですね(´・ω・`)これを適用することで、Queueでのappend呼び出しの際に元々想定していた要素型だけでなくそのスーパー型も利用できるから汎用的ですYO!ってのがコップ本の言い分みたいです。あと、変位指定と組み合わせることで型エラーを招かないで、異なる要素型を持つ待ち行列を自然にモデリング出来るとか…

…(´ε`;)ウーン…ニュアンスはわかるような気がするけども、あまり理解出来ていないなぁ、
と。この章はあとでやり直さないとだめだな(´;ω;`)

型駆動設計

ここ数回でやった変位指定アノテーションと下限境界の組み合わせで上手くいくように調整する方法を、型駆動設計と呼ぶみたいですね。具体的にはインターフェースの型が詳細設計と実装を導く…みたいな感じみたいです。

Javaなんかだとワイルドカードのような利用者側での変位指定なので、使い方を間違えるとインスタンスメソッドが使えなかったりするらしい(しかも変位指定は難しいのでミス連発らしい)んですが、Scalaでは宣言的変位指定を採用することでコンパイラーによるチェックが行えますよ、とのことでした。

うん、型(を避けてきた)初心者にはちょっぴりハードルが高い内容でしたな。

いじょー

とりあえず時間の都合でココマデです。まだまだ続くよ19章の型パラメータってことで…早めに終われるようにがんばります(´・ω・`)ちょっと苦手な分野ではあるけども、キーワードぐらいは覚えていけるようにしたいなぁ、いやほんとに