ScalaのTraitを使ってみる
30分プログラム、その442。なんとなくtraitを使ってみたかったので、RubyのEnumerableっぽいやつを作ってみた。
foreachを実装した上でEnumerable traitをくっつけると、mapとfilter、concatMapのデフォルト実装が使えるようになる。
class MySet[T <% Ordered[T]] extends ForEach[T] with Enumerable[T] { // foreachだけを実装する def foreach(x : T => Unit) : Unit = .... }
使い方
scala> val s : MySet[Int] = new MySet s: MySet[Int] = MySet@1301061 scala> s.insert(1) scala> s.insert(1) scala> s.insert(2) scala> s.insert(3) // foreachは実装してる scala> s.foreach(println(_)) 1 2 3 // mapが使える scala> s.map((x : Int) => x) res5: List[Int] = List(1, 2, 3) // mapがあるので、for式も使える scala> for(x <- s) yield x res8: List[Int] = List(1, 2, 3)
ソースコード
import scala.collection.mutable.ListBuffer trait ForEach[T] { def foreach(x : T => Unit) : Unit } trait Enumerable[T] extends ForEach[T]{ def map[S](f : T => S) : List[S] = { val xs : ListBuffer[S] = new ListBuffer() this.foreach { x => xs += f(x) } xs toList } def filter(f : T => Boolean) : List[T] = { val xs : ListBuffer[T] = new ListBuffer() this.foreach { x => if(f(x)) xs += x } xs toList } def concatMap[S](f : T => Iterable[S]) : List[S] = { val xs : ListBuffer[S] = new ListBuffer() this.foreach { x => xs ++= f(x) } xs toList } } class MySet[T <% Ordered[T]] extends ForEach[T] with Enumerable[T] { private var xs : List[T] = List() private def ins(x : T,xs : List[T]) : List[T] = xs match { case List() => List(x) case y::ys => if(y < x) y :: ins(x,ys) else if(y==x) xs else x :: xs } def insert(x : T) : Unit = xs = ins(x,this.xs) def foreach(f : T => Unit) : Unit = xs foreach f }