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.