我有一个类和它的同伴对象一起有一些可重复使用的功能。 我已经封装同伴对象的功能为特点,所以现在的情况是这样
class Foo {
import Foo._
def foo: Quux = bar(this)
}
trait Bar {
def bar(f: Foo): Quux = frobnicate(f)
}
object Foo extends Bar
由于Foo.foo
是可重复使用的方法,我想放入它的特质。
但是,我必须找到一种方法来告诉检查的类型,虽然bar
是不是在类中的方法Foo
,它会在范围,因为来自同伴对象导入。 我想,我需要这样的东西能够在键入类的同伴对象。
有什么样的?
有多种方式为您在斯卡拉需要的抽象模型。 我会先介绍最简单的模式,并分析你的问题,然后我将描述最复杂的图案,这是在Scala集合使用。
首先要注意的事情是,同伴的对象是把代码,你需要,而无需你的类的实例来调用,而地方分解出你在实例方法使用的特点 助手在正确的地方。 此外,智能Scala编译器会为您性状的单一静态方法,并链接所有这些将使用它给它的类。
但从你的代码来看,它是很容易看到它是如何被分解成一个特征,然后通过使用自型符号,一个可以强制性状FooTrait只有在特质酒吧混合混合为好。
class Foo extends FooTrait with Bar
trait FooTrait {
self:Bar =>
def foo: Quux = bar(this)
}
trait Bar {
def bar(f: Foo): Quux = frobnicate(f)
}
另请注意,如果你不想通过你的Foo类揭露栏界面,另一种方法是以下
class Foo extends FooTrait {
protected val barrer = Foo
}
trait FooTrait {
protected val barrer:Bar
def foo: Quux = barrer.bar(this)
}
trait Bar {
def bar(f: Foo): Quux = frobnicate(f)
}
object Foo extends Bar
当你把一个类和一个同伴对象第二种方法工作得很好,但是当你要开发的类层次,你现在没有可用于每个类的同伴对象不能很好地扩展,并且还希望执行该同伴对象具有相对于所述“companed类”某些特性。
还有一个更复杂的方法,这是在Scala集合使用,我热烈推荐你不要,除非绝对必要使用。
让我们从GenTraversable开始:
trait GenTraversable[+A]
extends GenTraversableLike[A, GenTraversable[A]]
with GenTraversableOnce[A]
with GenericTraversableTemplate[A, GenTraversable]
{
def seq: Traversable[A]
def companion: GenericCompanion[GenTraversable] = GenTraversable
}
object GenTraversable extends GenTraversableFactory[GenTraversable] {
implicit def canBuildFrom[A] = new GenericCanBuildFrom[A]
def newBuilder[A] = Traversable.newBuilder
}
正如所看到的,所述性状限定同伴对象,它提供了构建的相同类型的新的集合的一些基本基础设施(通常用于过滤,映射等)。
通过在层次结构往上走,你可以看到def companion
精制而成:
trait GenIterable[+A]
extends GenIterableLike[A, GenIterable[A]]
with GenTraversable[A]
with GenericTraversableTemplate[A, GenIterable]
{
def seq: Iterable[A]
override def companion: GenericCompanion[GenIterable] = GenIterable
}
object GenIterable extends GenTraversableFactory[GenIterable] {
implicit def canBuildFrom[A] = new GenericCanBuildFrom[A]
def newBuilder[A] = Iterable.newBuilder
}
如果你浏览类之间,你就会明白,这种机制是用来保证每个具体的集合实现,存在范围同伴用某种性质相对于类本身。 这是可能的,因为它是合法的细化方法的返回类型的子类。
尽管如此,为了正常工作,这个机制需要一些人工管型和大量的泛型参数,以及通用签名。
trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance] {
protected[this] def newBuilder: Builder[A, CC[A]] = companion.newBuilder[A]
/** The generic builder that builds instances of $Coll
* at arbitrary element types.
*/
def genericBuilder[B]: Builder[B, CC[B]] = companion.newBuilder[B]
private def sequential: TraversableOnce[A] =this.asInstanceOf[GenTraversableOnce[A]].seq
// other code
}
也许你需要一个自我类型 ?
trait Foo { self: Bar => // This says that anything that will mix in Foo
// must mix in Bar too.
def foo: Quux = bar(this)
}
trait Bar {
def bar(f: Foo): Quux = frobnicate(f)
}
object Foo extends Foo with Bar