在Scala中的伴生对象上键入
我有一个类和它的伴生对象,它们一起具有一些可重用的功能。我已经将同伴对象的功能封装到一个trait中,所以现在的情况如下在Scala中的伴生对象上键入,scala,types,companion-object,Scala,Types,Companion Object,我有一个类和它的伴生对象,它们一起具有一些可重用的功能。我已经将同伴对象的功能封装到一个trait中,所以现在的情况如下 class Foo { import Foo._ def foo: Quux = bar(this) } trait Bar { def bar(f: Foo): Quux = frobnicate(f) } object Foo extends Bar 因为Foo.Foo是一种可重用的方法,所以我想把它放在它的特性中 但是我必须找到一种方法告诉类型检查器
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集合中使用的最复杂的模式 首先要注意的是,伴随对象是放置您需要调用的代码的正确位置,而无需类的实例,而在实例方法中使用的助手的位置是traits。此外,智能scala编译器将为您的trait生成一个静态方法,并将使用它的所有类链接到它 从代码的角度来看,很容易看出如何将其分解为特征,然后通过使用自类型表示法,可以强制要求仅当特征条也混合时,才能混合特征足迹
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类公开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
当您使用单个类和单个伴生对象时,第二种方法可以很好地工作,但当您想要开发一个类的层次结构,其中每个类都有一个伴生对象,并且您还想要强制伴生对象具有与对象相关的某些特征时,这种方法无法很好地扩展“同伴阶级”
还有一种更复杂的方法,在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
}
如您所见,trait定义了一个伴生对象,它为构建相同类型的新集合(通常用于过滤、映射等)提供了一些基本的基础结构
通过在层次结构中向上移动,您可以看到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-GenericTraversableTemplate[+A,+CC[X]你能澄清一下你希望在最后拥有的特质是什么吗?我不知道你想把foo
方法放在哪里。在一个新的特质中?是的,我想把它放在一个单独的特质中。哇,这是一个非常好的答案!非常感谢你!:-)
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
}