Как вы явно указываете параметризованный тип для экзистенциального типа в Scala? - PullRequest
2 голосов
/ 15 июля 2011

В Программирование в Scala , приведен следующий пример, показывающий, как ссылаться на класс Java с помощью символов подстановки.Метод javaSet2ScalaSet принимает тип T. Как правило, вы всегда можете явно указать параметризованный тип.Но в этом случае, когда (new Wild).contents является экзистенциальным, параметр нормального типа недопустим.

Компилятор может выполнить некоторую магию и вывести соответствующий параметр, когда javaSet2ScalaSet вызывается без параметра типа.Просмотр того, что компилятор предоставляет с помощью scalac –Xprint: typer, показывает, что ему присваивается значение? 0 для T. Это нельзя предоставить вручную.

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

  // This is a Java class with wildcards
  public class Wild {
    Collection<?> contents() {
      Collection<String> stuff = new Vector<String>();
      stuff.add("a");
      stuff.add("b");
      stuff.add("see");
      return stuff;
    }
  }

  import scala.collection.mutable.Set
  import java.util.Collection

  abstract class SetAndType {
    type Elem
    val set: Set[Elem]
  }

  def javaSet2ScalaSet[T](jset: Collection[T]): SetAndType = {
    val sset = Set.empty[T]  // now T can be named!

    val iter = jset.iterator
    while (iter.hasNext)
      sset += iter.next()

    return new SetAndType {
      type Elem = T
      val set = sset
    }
  }

val setAndType = javaSet2ScalaSet((new Wild).contents)

Ответы [ 2 ]

1 голос
/ 04 августа 2011

Это просто синтаксическое ограничение, а не внутреннее. Вот как вы можете это объявить:

def javaSet2ScalaSet[C <: Collection[T] forSome { type T }](jset: C): SetAndType = {
  val sset = Set.empty[T forSome { type T }]

  val iter = jset.iterator
  while (iter.hasNext)
    sset += iter.next()

  return new SetAndType {
    type Elem = T forSome { type T }
    val set = sset
  }
}
0 голосов
/ 17 июля 2011

(Q1) >> Это особый случай, который работает только для логического типа. << </p>

Компилятор не делает вывод, что тип вашей коллекции Java имеет тип Collection. Известно только, что это коллекция с элементами типа some .

(Q2) >> или есть какой-то способ явно указать тип? << </p>

Нет. Экзистенциальный тип не должен быть предоставлен. Это не свободная переменная для привязки (поскольку она уже связана).

Посмотрите на это так: предположим, что вы смогли предоставить тип. Затем вы ожидаете, что компилятор проверит, что предоставленный тип соответствует типу элементов в вашей коллекции Java. Но компилятор не может это определить. Поэтому, если они не будут совпадать, вы все равно узнаете об этом только во время выполнения.

Если вы хотите сообщить компилятору Scala, что вы знаете, что элементы в java-коллекции имеют тип String (например, вы хотите вызвать x.length), то вы можете привести элементы к asInstanceOf [String]. Но это не введет безопасность типов. Вы снова только узнаете во время выполнения, если это будет неправильно.

...