2014-06-22 38 views
0

我试图创建一个通用构建器隐式类型类用于基于生成器的测试,作为学习练习。下面的例子捕捉了基本的逻辑。 (而不是合并类型FooLike成员,GenBuilder将用于scalacheck二代特质的成员组合)在下面的编译错误类型多态隐式类编译错误

object Foo { 
    trait FooLike[A] { 
     def foo(a: A): String 
    } 

    object FooLike { 
     implicit object FooLikeInt extends FooLike[Int] { 
      override def foo(a: Int): String = a.toString 
     } 
    } 

    implicit class GenBuilder[T](self: T)(implicit f: FooLike[T]){ 

     private var _items = Set(self) 

     def |?|(that: GenBuilder[T]): GenBuilder[T] = { 
      _items = _items + that.self 
      this 
     } 

     def items: Set[String] = _items.toSet.map((a: T) => f.foo(a)) 
    } 

} 

object Test { 
    import Foo._ 
    import Foo.FooLike._ 
    def test = { 
     val res = 11 |?| 12 |?| 13 |?| 14 
     println(res.items) 
    } 
} 


Test.test 

结果:

/Users/pkinsky/genBuilder.scala:19: error: value self is not a member of Main.$anon.Foo.GenBuilder[T] 
      _items = _items + that.self 

这些编译器错误混淆了对我说:自我如何不能成为GenBuilder的成员[T]?

(注:我使用“斯卡拉$文件名”运行这是一个脚本,如果对Scala的类型系统巫术任何影响)

+1

如果在构造函数参数中放置'val self:T',该怎么办? – ggovan

+0

天啊,我是个白痴。只有case类自动公开没有val的构造函数参数。这不是深式的系统巫术,这是明显的拍打我的脸。 添加此评论作为回答,如果你想得分:) – pkinsky

回答

1

这不是的情况下,一些深层次类型的系统巫术,而是不同的方式,构造函数的参数在斯卡拉使用。

更改您的类头

implicit class GenBuilder[T](val self: T)(implicit f: FooLike[T]){ 

(注意VAL个体经营)将使selfGenBuilder的领域,而不是仅仅在constuctor /私下avaliable。

案例类自动完成它的所有参数。

0

下面的代码工作,不知何故。替换that.selfthat.getSelfdef getSelf: T = self导致它编译和工作,按预期打印Set(11, 12, 13, 14)。即将推出:我的下一个问题,我问为什么?为什么这项工作?

object Foo { 
    trait FooLike[A] { 
     def foo(a: A): String 
    } 

    object FooLike { 
     implicit object FooLikeInt extends FooLike[Int] { 
      override def foo(a: Int): String = a.toString 
     } 
    } 

    implicit class GenBuilder[T](self: T)(implicit f: FooLike[T]){ 

     private var _items = Set(self) 
     def getSelf: T = self 

     def |?|(that: GenBuilder[T]): GenBuilder[T] = { 
      that.getSelf 
      _items = _items + that.getSelf 
      this 
     } 

     def items: Set[String] = _items.toSet.map((a: T) => f.foo(a)) 
    } 

} 

object Test { 
    import Foo._ 
    import Foo.FooLike._ 
    def test = { 
     val res = 11 |?| 12 |?| 13 |?| 14 
     println(res.items) 
    } 
} 


Test.test