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!ってのがコップ本の言い分みたいです。あと、変位指定と組み合わせることで型エラーを招かないで、異なる要素型を持つ待ち行列を自然にモデリング出来るとか…
…(´ε`;)ウーン…ニュアンスはわかるような気がするけども、あまり理解出来ていないなぁ、
と。この章はあとでやり直さないとだめだな(´;ω;`)
いじょー
とりあえず時間の都合でココマデです。まだまだ続くよ19章の型パラメータってことで…早めに終われるようにがんばります(´・ω・`)ちょっと苦手な分野ではあるけども、キーワードぐらいは覚えていけるようにしたいなぁ、いやほんとに