переопределяемый параметр типа по умолчанию в Scala - PullRequest
3 голосов
/ 25 июня 2019

Я пытаюсь выставить класс, параметризованный с псевдонимом типа:

trait Tr[T] {
  var x: T = _
}

abstract class Foo {
  type MyParameter

  class SomeClass extends SomeOtherClass with Tr[MyParameter]
}

class Bar extends Foo {
  override type MyParameter = Int

  val myObj = new SomeClass
  myObj.x = 6
}

class Qux extends Foo {
  override type MyParameter = String

  val myObj = new SomeClass
  myObj.x = "hello" 
}

Это отлично работает.

Теперь я хотел бы указать значение по умолчанию для типа MyParameter. Как это:

abstract class Foo {
  type MyParameter = String
  // ...
}

// ...

class Qux extends Foo {
  val myObj = new SomeClass
  myObj.x = "hello"
}

Однако, если я сделаю это, класс Bar потерпит неудачу с ошибкой типа - очевидно, в этот момент SomeClass уже зафиксирован в String.

Что я могу сделать, чтобы это исправить? Альтернативно, какой другой подход я могу использовать для параметризации SomeClass типом, который имеет значение по умолчанию, но может быть переопределено в подклассах Foo?

Обратите внимание, что SomeClass будет более сложным, чем показано, поэтому я не хочу, чтобы пользователям приходилось переопределять определение SomeClass. Кроме того, все варианты использования X.SomeClass должны использовать один и тот же Tr[T], поэтому я не хочу делать SomeClass параметрируемым.

1 Ответ

1 голос
/ 25 июня 2019

Если вы пропустите задание, вы можете получить основную причину проблемы:

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait T[T] {
  var x: T = _
}

abstract class Foo {
  type Param = String

  class Child extends T[Param]
}

class Bar extends Foo {
  (new Child).x = "foo"
}

class Qux extends Foo {
  override type Param = Int
}

// Exiting paste mode, now interpreting.

<pastie>:26: error: overriding type Param in class Foo, which equals String;
 type Param has incompatible type
  override type Param = Int

Переопределение типа следует тем же правилам, что и переопределение def, val или var: переопределяющий тип должен быть совместим с типом, который он переопределяет.

Так же, как вы не можете переопределить toString, например, для возврата Int.

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Test {
  override def toString: Int = 1
}

// Exiting paste mode, now interpreting.

<pastie>:12: error: overriding method toString in class Object of type ()String;
 method toString has incompatible type
  override def toString: Int = 1
               ^

Я бы предложил разделить иерархию, поэтому, когда вам нужен Foo с Tr[String] на FooString, а если вам нужен другой тип, вы можете расширить Foo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...