Scala: явное указание контекста, связанного во втором конструкторе

Почему это разрешено:

class Foo[O: Option](s: String)
new Foo[Any]("foo")(None)

пока это не

class Foo[O: Option](s: String) {
    def this() = this("foo")(None)
}

сообщение компилятора:

Foo [O] не принимает параметры

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

1 ответ

Решение

Хорошая Книга говорит, что привязка к контексту эквивалентна неявному свидетельству.

Как отметил @gabriele-petronella:

class Foo[O](s: String)(implicit o: Option[O]) {
  def this() = this("foo")(None)
}

Но при наличии привязки к контексту парсер автоматически добавляет параметр доказательства:

    class Foo[O] extends scala.AnyRef {
      <paramaccessor> private[this] val s: String = _;
      implicit <synthetic> <paramaccessor> private[this] val evidence$1: Option[O] = _;
      def <init>(s: String)(implicit evidence$1: Option[O]) = {
        super.<init>();
        ()
      };
      def <init>()(implicit evidence$2: Option[O]) = {
        <init>("foo")(None)(evidence$2);
        ()
      }
    }

Так что ошибка связана с приложенным аргументом.

Также верно, что вы не можете ничего сделать во вторичном конструкторе, чтобы заставить параметр типа, то есть, создать его экземпляр для определенного типа arg. ( Смотрите здесь.)

Причина, по которой обходной путь работает, состоит в том, что None <:< Option[Nothing] <:< Option[O] для любого типа param.

Как отметил @gabriele-petronella, в компаньоне вы можете делать все, что угодно:

object Foo { def apply() = new Foo[Int]("five")(Some(5)) }

Возможно, компилятор может подождать, чтобы решить, какой конструктор вы хотите вызвать и затем требуется ли неявное, и игнорировать неявное для вашего вторичного ctor в этом случае. Но конструкторы намеренно просты в Scala.

Другие вопросы по тегам