开发者

Scala passing type parameters to object

开发者 https://www.devze.com 2022-12-26 04:17 出处:网络
In Scala v 2.7.7 I have a file with class Something[T] extends Other object Something extends OtherConstructor[Something]

In Scala v 2.7.7

I have a file with

class Something[T] extends Other

object Something extends OtherConstructor[Something]

This throws the error:

class Something takes type parameters

ob开发者_如何学JAVAject Something extends OtherConstructor[Something] {

However, I can't do this

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

It throws an error:

error: ';' expected but '[' found.

Is it possible to send type parameters to object? Or should I change and simply use Otherconstructor


You could use:

object Something extends OtherConstructor[Something[_]]

You will of course be restricted by having an existential type with no upper bound in place instead of a concrete type. This solution may not make sense and you might need one object per concrete type T, for those T's which you care about, e.g.

object StringSomething extends OtherConstructor[Something[String]]

But then this has the (possible) disadvantage that StringSomething is not the companion object of Something.

However, my advice would be don't start messing about designing generic APIs (especially self-referential ones like the above) unless you really, really know what you are doing. It will almost certainly end in tears and there are plenty of CORE Java API's which are terrible because of the way generics have been added (the RowSorter API on JTable being one example)


You can solve the general problem of needing object Foo[T] by moving the type parameter to the methods in 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)
}

If you really need one object per T, you can make a class, and have the type-free companion return it from 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
}

Note this will re-construct the Foo[T] companion on each call so you would want to keep it light and stateless.

An explicit solution the the problem above:

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
}


An object has to have a concrete type. The Scala object contruct is not a exception to this rule.

A valid definition is

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

where T is some concrete type.


Thanks for the answers

object Something extends OtherConstructor[Something[_]]

seems to be compiling (although I have yet to run/test that :-))

@oxbow_lakes, I've followed your advice - of avoiding the type system - till now but I've got to do it!!! I've been studying existential types, type-erasure and all that but its still not in my grasp :-(

0

精彩评论

暂无评论...
验证码 换一张
取 消