Ответ 1
Все, что я могу добавить, это:
def foo(implicit a: Int, b: String) = println(a, b)
implicit val i1 = 1
implicit val s = ""
val i2 = 2
foo(i2, implicitly[String])
Рассмотрим функцию:
def foo(implicit a:Int, b:String) = println(a,b)
.
Теперь предположим, что в области есть неявный String
и Int
(implicit val i1=1
), но мы хотим передать другой, не неявный Int
(val i2=2
) явно до foo
.
Как мы можем это сделать? Является ли это возможным? Спасибо за чтение.
Все, что я могу добавить, это:
def foo(implicit a: Int, b: String) = println(a, b)
implicit val i1 = 1
implicit val s = ""
val i2 = 2
foo(i2, implicitly[String])
В случае, если ваш метод имеет много неявных параметров (иногда я имею в моих проектах), и вы иногда хотите просто указать один из них явным и позволить другим разрешить неявно, вы можете написать implicitly
для каждого другого параметра, как показано в мой другой ответ. Но иногда вы меняете подпись этого метода или явный параметр находится в середине списка параметров, тогда вы можете сделать более читаемый код клиента со следующей конструкцией:
Предположим, что у вас есть некоторые типы и их неявные фиктивные объекты:
trait I1; implicit object I1 extends I1
trait I2; implicit object I2 extends I2
trait I3; implicit object I3 extends I3
trait I4; implicit object I4 extends I4
trait I5; implicit object I5 extends I5
trait I6; implicit object I6 extends I6
Теперь у вас есть ваш метод foo1
, который использует эти импликации:
def foo1(implicit i1: I1, i2: I2, i3: I3, i4: I4, i5: I5, i6: I6) {
println(i1, i2, i3, i4, i5, i6)
}
Теперь вы часто хотите явно указать i4: I4
. Итак, вы пишете:
val i4 = new I4 {}
foo1(implicitly, implicitly, implicitly, i4, implicitly, implicitly)
Гадкий!
Со следующим (следует поместить в узкую область применения метод foo2
и, возможно, переименованный) для всех имплицитов:
object Implicits {
def apply(i4: I4)(implicit i1: I1, i2: I2, i3: I3, i5: I5, i6: I6) = new Implicits(i1, i2, i3, i4, i5, i6)
implicit def applying(implicit i1: I1, i2: I2, i3: I3, i4: I4, i5: I5, i6: I6) = new Implicits(i1, i2, i3, i4, i5, i6)
}
class Implicits(val i1: I1, val i2: I2, val i3: I3, val i4: I4, val i5: I5, val i6: I6)
и связанный с ним метод foo2
:
def foo2(implicit implicits: Implicits) = {
import implicits._
println(i1, i2, i3, i4, i5, i6)
}
теперь вы можете вызывать foo2
вместо foo1
следующим образом:
locally {
foo2 // using implicit dummy objects I1, ..., I6 from above
// or with explicit I4:
val i4 = new I4 {}
foo2(Implicits(i4))
}
foo(i2, s1)
, но вы потеряете преимущество использования implicit String
def foo1(a: Int)(implicit b: String)=foo(a,b)
, и вы вызываете foo1(i2)
Я знаю, что это старый вопрос, но он все еще может быть интересным. Хороший способ сделать это - использовать неявно в качестве значения по умолчанию:
scala> def foo(a: Int = implicitly[Int], b: String = implicitly[String]) = println(a,b)
scala> foo()
(10,boo)
scala> foo(50)
(50,boo)
scala> foo(b="bar")
(10,bar)
Вы можете создать новую внутреннюю область и определить в ней новый неявный val. Преимущество заключается в том, что, когда у вас есть несколько вызовов функций, таким образом, вы можете переопределить одно неявное для всех из них в одном месте:
def foo(implicit a:Int, b:String) = println(a,b).
implicit val i = 1
implicit val s = ""
foo // call with original implicits
{
implicit val i = 2
foo // call with a new Int implicit
foo // call with a new Int implicit again
}
Примечание: новое неявное должно иметь то же имя переменной, что и исходное, поэтому оно скрывает его, иначе вы получите ошибку компилятора о неоднозначных неявных значениях.