Создание экземпляра псевдонима типа вызывает ошибку «требуется тип класса» - PullRequest
11 голосов
/ 07 ноября 2011

Создав новый тип, смешав ObservableSet с HashSet, я ожидал заменить, а затем смог бы использовать новый тип для создания нового экземпляра, как в "foo" ниже.Но это не компилируется, хотя использование оригинальной длинной формы этого типа выглядит нормально (как показано в «баре» ниже).

Это просто особенность языка или я сделал что-то глупое?

package whatever

import collection.mutable._
object Whatever {

  type ObservableHashSet[T] = HashSet[T]  with  ObservableSet[T]
  class X


  def foo {
       new  ObservableHashSet[X]
  }

   def bar {
    new HashSet[X]  with  ObservableSet[X]
  }
}

Ошибка ..

error: class type required but scala.collection.mutable.HashSet[scala.Whatever.X] with scala.collection.mutable.ObservableSet[scala.Whatever.X] found
new  ObservableHashSet[X]

1 Ответ

13 голосов
/ 08 ноября 2011

Краткая версия заключается в том, что вы создали псевдоним типа для структурного типа (создание которого невозможно).

Это упрощенная версия того, что вы сделали (не работает):

scala> import collection.mutable._
import collection.mutable._

scala> type ObservableHashSet[T] = HashSet[T]  with  ObservableSet[T]
defined type alias ObservableHashSet

scala> new ObservableHashSet[String]
<console>:12: error: class type required but scala.collection.mutable.HashSet[String] with scala.collection.mutable.ObservableSet[String] found new ObservableHashSet[String]

Теперь ошибка имеет какой-то смысл, и позвольте мне объяснить, почему.

С type ObservableHashSet[T] = HashSet[T] with ObservableSet[T] вы определяете псевдоним типа для чего-то, что не является конкретным типом (или, как говорится в сообщении об ошибке, а не "типом класса"), поэтому вы не можете создать его экземпляр new.

Но это (с промежуточным шагом, когда мы создаем тип класса) работает:

scala> class ObservableHashSet[T] extends HashSet[T]  with  ObservableSet[T]
defined class ObservableHashSet

scala> type obs[T] = ObservableHashSet[T]
defined type alias obs

scala> new obs[String]
res1: ObservableHashSet[String] = Set()

Итак, вопрос: почему scala позволяет вам создавать псевдоним типа, который вы не можете создать? Ну, type ObservableHashSet[T] = HashSet[T] with ObservableSet[T] это структурный тип. Хотя, как вы видели в первом фрагменте кода, вы не можете создать его экземпляр, вы все равно можете использовать его: например, наложить структурное ограничение на аргумент функции.

Взгляните:

scala> type ObservableHashSet[T] = HashSet[T]  with  ObservableSet[T]
defined type alias ObservableHashSet

scala> def test(obsHashSet: ObservableHashSet[String]) : String = {"bingo!"}
test: (obsHashSet: ObservableHashSet[String])String

scala> test(new HashSet[String]  with  ObservableSet[String])
res4: String = bingo!

но если мы попытаемся вызвать test с аргументом, который не соответствует структурному типу, мы получим несоответствие типов:

scala> test(new HashSet[String])
<console>:13: error: type mismatch;
 found   : scala.collection.mutable.HashSet[String]
 required: ObservableHashSet[String]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...