В последнее время среди блоггеров Scala наблюдается большой энтузиазм по поводу шаблона классов классов , в котором к простому классу добавлена функциональность с помощью дополнительного класса, соответствующего некоторой характеристике или шаблону.В качестве чрезвычайно упрощенного примера простой класс:
case class Wotsit (value: Int)
может быть адаптирован к признаку Foo:
trait Foo[T] {
def write (t: T): Unit
}
с помощью класса этого типа:
implicit object WotsitIsFoo extends Foo[Wotsit] {
def write (wotsit: Wotsit) = println(wotsit.value)
}
Класс типов обычно захватывается во время компиляции с последствиями, позволяя и Wotsit, и его классу типов передаваться вместе в функцию более высокого порядка:
def writeAll[T] (items: List[T])(implicit tc: Foo[T]) =
items.foreach(w => tc.write(w))
writeAll(wotsits)
(перед тем, как вы меня исправите, я сказалэто был упрощенный пример)
Однако , использование имплицитов предполагает, что точный тип элементов известен во время компиляции.Я обнаружил, что в моем коде это часто не так: у меня будет список элементов типа List [T], и мне нужно будет найти правильный класс типов для работы с ними.
Предлагаемый подходScala, по-видимому, заключается в добавлении аргумента класса типов во всех точках иерархии вызовов.Это может раздражать по мере масштабирования кода, и эти зависимости необходимо передавать по все более длинным цепочкам через методы, к которым они все более не имеют отношения.Это делает код беспорядочным и сложным в обслуживании, в отличие от того, для чего предназначен Scala.
Как правило, именно здесь начинается внедрение зависимостей, используя библиотеку для предоставления нужного объекта в нужной точке.Детали меняются в зависимости от библиотеки, выбранной для DI - в прошлом я писал свою собственную на Java - но, как правило, точка внедрения должна точно определять желаемый объект.
Проблема в случае типаКласс точное значение не известно во время компиляции.Он должен быть выбран на основе полиморфного описания.И что особенно важно, информация о типе была стерта компилятором.Манифесты - это решение Scala для стирания типов, но мне далеко не ясно, как их использовать для решения этой проблемы.
Какие методы и библиотеки внедрения зависимостей для Scala предложат в качестве способа решения этой проблемы?Я пропускаю трюк?Идеальная библиотека DI?Или это действительно тот самый камень преткновения, который кажется?
Разъяснение
Я думаю, что в этом действительно есть два аспекта.В первом случае точка, где нужен класс типов, достигается прямыми вызовами функций из точки, где известен точный тип ее операнда, и, таким образом, достаточный спор типа и синтаксический сахар могут позволить классу типа быть переданным вточка, в которой это необходимо.
Во втором случае две точки разделяются барьером - таким как API, который нельзя изменить, или хранится в базе данных или хранилище объектов, или сериализуется и отправляется вдругой компьютер - это означает, что класс типа не может быть передан вместе с его операндом.В этом случае, учитывая объект, тип и значение которого известны только во время выполнения, класс типа должен как-то быть обнаружен.
Я думаю, что функциональные программисты имеют привычку предполагать первый случай - тот, что с достаточно продвинутымязык, тип операнда всегда будет известен.Дэвид и mkniessl дали хорошие ответы на это, и я, конечно, не хочу их критиковать.Но второй случай определенно существует, и именно поэтому я включил вопрос о зависимостях.