Когда мы будем использовать scala.util.DynamicVariable?
Когда я прочитал источник скаляры, я обнаружил, что есть код:
protected val _response = new DynamicVariable[HttpServletResponse](null)
protected val _request = new DynamicVariable[HttpServletRequest](null)
Существует интересный класс с именем DynamicVariable
. Я просмотрел документ этого класса, но я не знаю, когда и почему мы должны его использовать? Он имеет withValue()
, который обычно используется.
Если мы его не используем, то какой код мы должны использовать вместо этого, чтобы решить проблему, которую он решил?
(Я новичок в scala, если вы можете предоставить некоторый код, это будет здорово)
Ответы
Ответ 1
DynamicVariable
- это реализация шаблонов займов и динамических областей. Пример использования DynamicVariable
в значительной степени похож на ThreadLocal
в Java (по сути, DynamicVariable
использует InheritableThreadLocal
за кулисами) - он использовался, когда вам нужно выполнить вычисление в закрытой области, где каждый поток имеет свою собственную копию значения переменной:
dynamicVariable.withValue(value){ valueInContext =>
// value used in the context
}
Учитывая, что DynamicVariable
использует наследуемый ThreadLocal
, значение переменной передается потокам, порожденным в контексте:
dynamicVariable.withValue(value){ valueInContext =>
spawn{
// value is passed to the spawned thread
}
}
DynamicVariable
(и ThreadLocal
) используется в Scalatra по той же причине, что и во многих других средах (Lift, Spring, Struts и т.д.) - это неинтрузивный способ хранения и передачи контекст (поток) - конкретная информация.
Создание динамических переменных HttpServletResponse
и HttpServletRequest
(и, таким образом, привязка к определенному потоку, обрабатывающему запрос), - это самый простой способ получить их в любом месте кода (не проходя через аргументы метода или в любом случае явно).
Ответ 2
На это хорошо ответил Василь, но я добавлю еще один простой пример, который может помочь понять.
Предположим, что мы должны использовать некоторый код, который использует println() для записи всего stdout. Мы хотим, чтобы этот вывод попадал в файл журнала, но у нас нет доступа к источнику.
-
println()
использует Console.println()
-
Console.println()
(к счастью) на основе a DynamicVariable[PrintStream]
, который по умолчанию равен java.lang.System.out
-
Console
определяет withOut
, который просто переходит к динамической переменной withValue
Мы можем использовать это, чтобы просто исправить нашу проблему:
def noisy() { println("robot human robot human") }
noisy() // prints to stdout
val ps = new java.io.PrintStream("/tmp/mylog")
scala.Console.withOut(ps) { noisy() } // output now goes to /tmp/mylog file
Ответ 3
Это минимальный фрагмент:
val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
print
}
print
Выход будет:
withoutValue
withValue
withoutValue