2011-09-02 昨日?の続き
抽象型について考えてみる2
昨日(id:seraphr:20110901)の続き
@seraphr 抽象型 + 自分型注釈 の実装(私)と Genericsによる実装を比べてみるとわかると思うんですが、Genericsによる実装は「重複コード」が多いわけです。 #scalajp
2011-09-01 21:50:24 via Tween to @seraphr
@seraphr つまり、Genericsによる拡張可能なVisitorパターンはうまくモジュール化されていないといえるかと。 #scalajp
2011-09-01 22:49:50 via Tween to @seraphr
@kmizu そうして考えると、Genericsと抽象型は影響範囲が違うんですね。 Genericsは型と共に宣言されるのでその型の内部にしか影響を与えられないけど、抽象型はメンバーとして宣言されるので他のメンバーにも影響を与えられる。 *Tw*
2011-09-02 00:39:37 via Twit for Windows to @kmizu
@kmizu 逆に、Generics型の内部クラスを参照できないかとclass VisitorsBaseGenerics[V <: VisitorsBaseGenerics[V]#Visitor]とか書いてみましたけどvisitメソッドの引数の型が合わないと怒られますね *Tw*
2011-09-02 00:39:55 via Twit for Windows to @kmizu
ってことで、抽象型は『コードの再利用』とはちょっと違う感じだけど、DRY原則的に重要になってくる概念ってことなのかな。
確かに、実際自己言及するジェネリックスを大量に使ってグループ化したクラス群を定義したライブラリとか、書いたことあるけど、下手に型引数の数とかが変わると変更が波及したりして色々大変だし、その点でも色々嬉しそう。
んで↑のツイートでも言っているけれども、Genericsクラスの内部クラスを参照して、Genericsを定義すれば、同じ効果が得られるんじゃないか、と思って書いたのが以下のコード。 ↑のツイートしてから、もうちょっと頑張ってみたんだけど、なんかコンパイラから『error: java.lang.AssertionError: assertion failed: VisitorsPlusGenerics[V]』って怒られてコンパイルが通らなくなっちゃった。
文法的に通らないとか、型が解決できないとかならわかるんだけど、assertion failedって何が原因なんだろう…
trait VisitorsBaseGenerics[V <: VisitorsBaseGenerics[V]#Visitor] { self => trait Node { def accept(v: V) } case class Add(l: Node, r: Node) extends Node { def accept(v: V) { v.visit(this) } } case class Sub(l: Node, r: Node) extends Node { def accept(v: V) { v.visit(this) } } case class Value(value: Int) extends Node { def accept(v: V) { v.visit(this) } } trait Visitor { self: V => def visit(node: VisitorsBaseGenerics[V]#Add) { println("Add!") node.l.accept(this) node.r.accept(this) } def visit(node: VisitorsBaseGenerics[V]#Sub) { println("Sub!") node.l.accept(this) node.r.accept(this) } def visit(node: VisitorsBaseGenerics[V]#Value) { println("Value: " + node.value) } } } class VisitorsPlusGenerics[V <: VisitorsPlusGenerics[V]#Visitor] extends VisitorsBaseGenerics[V] { case class Mul(l: Node, r: Node) extends Node { def accept(v: V) { v.visit(this) } } case class Div(l: Node, r: Node) extends Node { def accept(v: V) { v.visit(this) } } class Visitor extends super.Visitor { self: V => def visit(node: VisitorsPlusGenerics[V]#Mul) { println("Mul") node.l.accept(this) node.r.accept(this) } def visit(node: VisitorsPlusGenerics[V]#Div) { println("Div") node.l.accept(this) node.r.accept(this) } } } object VisitorGenericsMain { val mVisitorContainer = new VisitorsPlusGenerics[UseVisitor] import mVisitorContainer._ class UseVisitor extends Visitor def main(args: Array[String]) { val v = new UseVisitor Add(Value(1), Value(2)).accept(v) Sub(Value(1), Value(2)).accept(v) Mul(Value(1), Value(2)).accept(v) Div(Value(1), Value(2)).accept(v) } }
以下が発生するエラー
>scalac VisitorGenericsMain.scala error: java.lang.AssertionError: assertion failed: jp.seraphr.scala.hello.HelloScala.generics.VisitorsPlusGenerics[V] at scala.Predef$.assert(Predef.scala:103) at scala.tools.nsc.ast.TreeGen.mkAttributedQualifier(TreeGen.scala:66) at scala.tools.nsc.ast.TreeGen.mkAttributedQualifier(TreeGen.scala:44) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.mixinOuterAccessorDef(ExplicitOuter.scala:351) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1$$anonfun$apply$mcV$sp$1.apply(ExplicitOuter.scala:457) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1$$anonfun$apply$mcV$sp$1.apply(ExplicitOuter.scala:455) at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59) at scala.collection.immutable.List.foreach(List.scala:45) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1.apply$mcV$sp(ExplicitOuter.scala:455) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1.apply(ExplicitOuter.scala:448) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1.apply(ExplicitOuter.scala:448) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:447) at scala.tools.nsc.ast.Trees$Transformer.transformTemplate(Trees.scala:875) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:767) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:766) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:765) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:53) at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:257) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:521) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats$1.apply(Trees.scala:891) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats$1.apply(Trees.scala:889) at scala.collection.immutable.List.loop$1(List.scala:117) at scala.collection.immutable.List.mapConserve(List.scala:133) at scala.tools.nsc.ast.Trees$Transformer.transformStats(Trees.scala:889) at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:797) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.scala$tools$nsc$transform$TypingTransformers$TypingTransformer$$super$transform(TypingTransformers.scala:49) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$$anonfun$transform$1.apply(TypingTransformers.scala:49) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$$anonfun$transform$1.apply(TypingTransformers.scala:49) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:49) at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:257) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:460) at scala.tools.nsc.ast.Trees$Transformer.transformTemplate(Trees.scala:875) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:767) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:766) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:765) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:53) at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:257) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:521) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats$1.apply(Trees.scala:891) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats$1.apply(Trees.scala:889) at scala.collection.immutable.List.loop$1(List.scala:117) at scala.collection.immutable.List.mapConserve(List.scala:133) at scala.tools.nsc.ast.Trees$Transformer.transformStats(Trees.scala:889) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$1.apply(Trees.scala:761) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$1.apply(Trees.scala:761) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:760) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.scala$tools$nsc$transform$TypingTransformers$TypingTransformer$$super$transform(TypingTransformers.scala:49) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$$anonfun$transform$2.apply(TypingTransformers.scala:51) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$$anonfun$transform$2.apply(TypingTransformers.scala:51) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:51) at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:257) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:521) at scala.tools.nsc.ast.Trees$Transformer.transformUnit(Trees.scala:892) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.scala$tools$nsc$transform$ExplicitOuter$ExplicitOuterTransformer$$super$transformUnit(ExplicitOuter.scala:529) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transformUnit$1.apply(ExplicitOuter.scala:529) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transformUnit$1.apply(ExplicitOuter.scala:529) at scala.tools.nsc.symtab.SymbolTable.atPhase(SymbolTable.scala:96) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transformUnit(ExplicitOuter.scala:529) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transformUnit(ExplicitOuter.scala:318) at scala.tools.nsc.transform.Transform$Phase.apply(Transform.scala:30) at scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply(Global.scala:326) at scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply(Global.scala:326) at scala.tools.nsc.reporters.Reporter.withSource(Reporter.scala:47) at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:326) at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:294) at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:294) at scala.collection.Iterator$class.foreach(Iterator.scala:652) at scala.collection.mutable.ListBuffer$$anon$1.foreach(ListBuffer.scala:311) at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:294) at scala.tools.nsc.transform.ExplicitOuter$Phase.run(ExplicitOuter.scala:539) at scala.tools.nsc.Global$Run.compileSources(Global.scala:949) at scala.tools.nsc.Global$Run.compile(Global.scala:1034) at scala.tools.nsc.Main$.process(Main.scala:106) at scala.tools.nsc.Main$.main(Main.scala:123) at scala.tools.nsc.Main.main(Main.scala) Exception in thread "main" java.lang.AssertionError: assertion failed: jp.seraphr.scala.hello.HelloScala.generics.VisitorsPlusGenerics[V] at scala.Predef$.assert(Predef.scala:103) at scala.tools.nsc.ast.TreeGen.mkAttributedQualifier(TreeGen.scala:66) at scala.tools.nsc.ast.TreeGen.mkAttributedQualifier(TreeGen.scala:44) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.mixinOuterAccessorDef(ExplicitOuter.scala:351) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1$$anonfun$apply$mcV$sp$1.apply(ExplicitOuter.scala:457) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1$$anonfun$apply$mcV$sp$1.apply(ExplicitOuter.scala:455) at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59) at scala.collection.immutable.List.foreach(List.scala:45) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1.apply$mcV$sp(ExplicitOuter.scala:455) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1.apply(ExplicitOuter.scala:448) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transform$1.apply(ExplicitOuter.scala:448) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:447) at scala.tools.nsc.ast.Trees$Transformer.transformTemplate(Trees.scala:875) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:767) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:766) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:765) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:53) at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:257) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:521) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats$1.apply(Trees.scala:891) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats$1.apply(Trees.scala:889) at scala.collection.immutable.List.loop$1(List.scala:117) at scala.collection.immutable.List.mapConserve(List.scala:133) at scala.tools.nsc.ast.Trees$Transformer.transformStats(Trees.scala:889) at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:797) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.scala$tools$nsc$transform$TypingTransformers$TypingTransformer$$super$transform(TypingTransformers.scala:49) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$$anonfun$transform$1.apply(TypingTransformers.scala:49) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$$anonfun$transform$1.apply(TypingTransformers.scala:49) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:49) at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:257) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:460) at scala.tools.nsc.ast.Trees$Transformer.transformTemplate(Trees.scala:875) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:767) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$2.apply(Trees.scala:766) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:765) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:53) at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:257) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:521) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats$1.apply(Trees.scala:891) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats$1.apply(Trees.scala:889) at scala.collection.immutable.List.loop$1(List.scala:117) at scala.collection.immutable.List.mapConserve(List.scala:133) at scala.tools.nsc.ast.Trees$Transformer.transformStats(Trees.scala:889) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$1.apply(Trees.scala:761) at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform$1.apply(Trees.scala:761) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:760) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.scala$tools$nsc$transform$TypingTransformers$TypingTransformer$$super$transform(TypingTransformers.scala:49) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$$anonfun$transform$2.apply(TypingTransformers.scala:51) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$$anonfun$transform$2.apply(TypingTransformers.scala:51) at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:38) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.atOwner(TypingTransformers.scala:31) at scala.tools.nsc.transform.TypingTransformers$TypingTransformer.transform(TypingTransformers.scala:51) at scala.tools.nsc.transform.ExplicitOuter$OuterPathTransformer.transform(ExplicitOuter.scala:257) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transform(ExplicitOuter.scala:521) at scala.tools.nsc.ast.Trees$Transformer.transformUnit(Trees.scala:892) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.scala$tools$nsc$transform$ExplicitOuter$ExplicitOuterTransformer$$super$transformUnit(ExplicitOuter.scala:529) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transformUnit$1.apply(ExplicitOuter.scala:529) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer$$anonfun$transformUnit$1.apply(ExplicitOuter.scala:529) at scala.tools.nsc.symtab.SymbolTable.atPhase(SymbolTable.scala:96) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transformUnit(ExplicitOuter.scala:529) at scala.tools.nsc.transform.ExplicitOuter$ExplicitOuterTransformer.transformUnit(ExplicitOuter.scala:318) at scala.tools.nsc.transform.Transform$Phase.apply(Transform.scala:30) at scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply(Global.scala:326) at scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply(Global.scala:326) at scala.tools.nsc.reporters.Reporter.withSource(Reporter.scala:47) at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:326) at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:294) at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:294) at scala.collection.Iterator$class.foreach(Iterator.scala:652) at scala.collection.mutable.ListBuffer$$anon$1.foreach(ListBuffer.scala:311) at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:294) at scala.tools.nsc.transform.ExplicitOuter$Phase.run(ExplicitOuter.scala:539) at scala.tools.nsc.Global$Run.compileSources(Global.scala:949) at scala.tools.nsc.Global$Run.compile(Global.scala:1034) at scala.tools.nsc.Main$.process(Main.scala:106) at scala.tools.nsc.Main$.main(Main.scala:123) at scala.tools.nsc.Main.main(Main.scala)
- 5 http://t.co/rhqino3
- 1 http://d.hatena.ne.jp/keyword/SCALA
- 1 http://reader.livedoor.com/reader/
- 1 http://t.co/KDwwypz
- 1 http://www.google.co.jp/
- 1 http://www.google.co.jp/search?q=TypeFilterLevel&btnG=検索&sourceid=navclient&hl=ja&rlz=1T4ADFA_jaJP376JP386&aq=f&aqi=&aql=&oq=
- 1 http://www.google.com/search?hl=ja&newwindow=1&safe=off&q=抽象型+scala+ジェネリクス&oq=抽象型+scala+ジェネリクス&aq=f&aqi=&aql=&g
- 1 http://www.google.com/search?q=抽象型+scala+ジェネリクス&hl=ja&newwindow=1&safe=off&prmd=ivns&ei=MfFgTtbmNK_nmAWX35zeDQ&start=10&sa=N&biw=1304&bih=683