And*_*rea 7 types scala companion-object
我有一个类及其伴随对象,它们共同具有一些可重用的功能.我已将伴随对象的功能封装成特征,所以现在的情况就像
class Foo {
import Foo._
def foo: Quux = bar(this)
}
trait Bar {
def bar(f: Foo): Quux = frobnicate(f)
}
object Foo extends Bar
Run Code Online (Sandbox Code Playgroud)
既然Foo.foo是一种可重用的方法,我想把它放到它的特性中.
但我必须找到一种方法来告诉类型检查器,虽然bar不是类的方法Foo,但它将在范围内,因为从伴随对象导入.我想我需要能够键入类的伴随对象.
有类似的东西吗?
有多种方法可以在Scala中对所需的抽象进行建模.我将首先描述最简单的模式并分析您的问题,然后我将描述最复杂的模式,它在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)
}
Run Code Online (Sandbox Code Playgroud)
另请注意,如果您不希望通过Foo类公开Bar接口,则可以采用以下替代方法
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
Run Code Online (Sandbox Code Playgroud)
当你使用单个类和单个伴随对象时,第二种方法可以正常工作,但是当你想要开发类的层次结构时,你现在有一个可用于这些类的每个类的伴随对象,并且你也想要强制执行伴侣对象具有"比较阶级"的某些特征.
有一种更复杂的方法,在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
}
Run Code Online (Sandbox Code Playgroud)
如您所见,该特征定义了一个伴随对象,它为构建相同类型的新集合提供了一些基本的基础结构(通常用于过滤,映射等).
通过在层次结构中上升,您可以看到它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
}
Run Code Online (Sandbox Code Playgroud)
如果你在类之间浏览,你会明白这个机制用于保证对于每个具体的集合实现,在范围内有一个伴随着类本身的某种属性.这是可能的,因为在子类中细化方法的返回类型是合法的.
然而,为了正常工作,这种机制需要一些手动转换和许多通用参数,以及通用签名.
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
}
Run Code Online (Sandbox Code Playgroud)