Scala将类型参数传递给对象

时间:2010-04-07 14:58:26

标签: scala object type-parameter

在Scala v 2.7.7中

我有一个带

的文件
class Something[T] extends Other

object Something extends OtherConstructor[Something]

这会引发错误:

  

class Something采用类型参数
  object Something extends OtherConstructor [Something] {

但是,我不能这样做

object Something[T] extends OtherConstructor[Something[T]]

抛出错误:

  

错误:';'预期,但'''发现。

是否可以将类型参数发送给对象?或者我应该改变并简单地使用Otherconstructor

4 个答案:

答案 0 :(得分:4)

您可以使用:

object Something extends OtherConstructor[Something[_]]

您当然会受到限制,因为存在类型没有上限而不是具体类型。这个解决方案可能没有意义,每个具体类型T可能需要一个对象,对于那些你关心的T,例如。

object StringSomething extends OtherConstructor[Something[String]]

但是这有(可能)的缺点,StringSomething不是Something的伴侣对象。

然而,我的建议是不要开始搞乱设计通用API (特别是上面提到的自我引用的),除非你真的,真的知道你是什么是做。它几乎肯定会流泪,因为添加了泛型的方式(RowSorter上的JTable API就是一个例子),有很多CORE Java API很糟糕。

答案 1 :(得分:3)

对象必须具有具体类型。 Scala对象构造不是此规则的例外。

有效的定义是

object Something extends OtherConstructor[Something[T]] { }

其中T具体类型

答案 2 :(得分:2)

您可以通过将type参数移动到object Foo[T]中的方法来解决需要object Foo的一般问题:

class Foo[T](t1: T, t2: T)

object Foo {
  def apply[T](x: T): Foo[T] = new Foo(x, x)
  def apply[T](x: T, y: T): Foo[T] = new Foo(x, y)
}

如果你真的需要每个T一个对象,你可以创建一个类,并让无类型的伴侣从apply中返回它。

class Foo[T](t1: T, t2: T)

class FooCompanion[T] {
  def apply(x: T): Foo[T] = new Foo(x, x)
  def apply(x: T, y: T): Foo[T] = new Foo(x, y)
}

object Foo {
  def apply[T] = new FooCompanion[T]
}

object demo extends App {
  val x: Foo[Double] = Foo.apply.apply(1.23)  // this is what is really happening
  val y: Foo[Int] = Foo[Int](123)             // with the type both apply calls are automatic
}

请注意,这将在每次调用时重新构建Foo [T]伴侣,因此您可能希望保持轻量级和无状态。

明确解决上述问题:

class Other

class OtherConstructor[O <: Other] {
  def apply(o: O): O = o  // constructor 1 in base class
}

class Something[T](value: T) extends Other

class SomethingConstructor[T] extends OtherConstructor[Something[T]] {
  def apply(o: T, s: String) = new Something[T](o)   // constructor 2 in subclass
}

object Something {
  def apply[T] = new SomethingConstructor[T] // the "constructor constructor" method
}

object demoX extends App {
  val si = new Something(123)
  val sd = new Something(1.23)

  val si1: Something[Int] = Something[Int](si)                    // OtherConstructor.apply
  val sd1: Something[Double] = Something[Double](1.23, "hello")   // SomethingConstructor[Double].apply
}

答案 3 :(得分:1)

感谢答案

object Something extends OtherConstructor[Something[_]]

似乎正在编译(虽然我还没有运行/测试: - ))

@oxbow_lakes,我遵循了你的建议 - 避免使用类型系统 - 直到现在,但我必须这样做! 我一直在研究存在主义类型,类型擦除等等但它仍然不在我的掌握之中: - (