Scala передает параметры типа объекту - PullRequest
10 голосов
/ 07 апреля 2010

In Scala v 2.7.7

У меня есть файл с

class Something[T] extends Other

object Something extends OtherConstructor[Something]

Это выдает ошибку:

класс Что-то принимает параметры типа
объект Something расширяет OtherConstructor [Something] {

Однако я не могу этого сделать

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

Выдает ошибку:

ошибка: ';' ожидается, но '[' найдено.

Можно ли отправить параметры типа объекту? Или я должен изменить и просто использовать Otherconstructor

Ответы [ 4 ]

4 голосов
/ 07 апреля 2010

Вы можете использовать:

object Something extends OtherConstructor[Something[_]]

Конечно, вы будете ограничены наличием экзистенциального типа без верхней границы вместо конкретного типа.Это решение может не иметь смысла, и вам может понадобиться один объект для каждого конкретного типа T, для тех T, которые вас интересуют, например,

object StringSomething extends OtherConstructor[Something[String]]

Но тогда это имеет (возможный) недостаток, что StringSomethingне является сопутствующим объектом Something.

Тем не менее, мой совет будет не начинайте возиться с разработкой универсальных API (особенно самоссылающихся, как указано выше), если только вы на самом деле действительно знаю, что ты делаешь.Это почти наверняка закончится слезами, и есть множество CORE Java API, которые ужасны из-за того, как были добавлены дженерики (API RowSorter на JTable является одним из примеров)

3 голосов
/ 07 апреля 2010

Объект должен иметь конкретный тип. Конструкция объекта Scala не является исключением из этого правила.

Допустимое определение:

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

, где T - это некоторый конкретный тип .

2 голосов
/ 05 ноября 2017

Вы можете решить общую проблему необходимости 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
}
1 голос
/ 09 апреля 2010

Спасибо за ответы

object Something extends OtherConstructor[Something[_]]

, кажется, компилируется (хотя мне еще предстоит запустить / проверить это: -))

@ oxbow_lakes, я следовалВаш совет - избегать системы типов - до сих пор, но я должен это сделать !!!Я изучал экзистенциальные типы, стирание типов и все такое, но это все еще не в моих руках: - (

...