#scala
#scala
Вопрос:
Было задано несколько вопросов, которые в некоторой степени связаны с этой проблемой, но, похоже, они не совсем подходят.
Я использую шаблон Cake, чтобы внедрить систему «Хранения» в производственный код, а систему хранения заглушек — в целях тестирования. Это все замечательно, но есть класс, который создается внутри исходного класса, к которому также должна быть подключена эта система хранения заглушек. Поскольку он скрыт внутри реализации, у меня нет к нему доступа.
Все выглядит следующим образом:
class Main { this: Storage =>
...
val used = Used(...)
...
}
class Used { this: Storage =>
...
}
При тестировании «Used» я просто new Used with StubStorage
и ухожу. Раньше я делал то же самое с Main
, но это было до того, как он начал использовать Used
. Теперь, когда Main
создается наивный экземпляр Used
, у меня возникла эта проблема.
Я хотел попробовать это таким образом:
class Main[T <: Storage] { this: T =>
...
val used = Used[T](...)
...
}
class Used[T <: Storage] { this: T =>
...
}
object Used {
def apply[T <: Storage](...) = new Used(...) with T
}
Но, конечно, это не работает, потому что компилятору недостаточно информации для обнаружения T
. Есть ли волшебный рецепт для этого? Я немного поиграл с ним, и он кажется достаточно громоздким, чтобы стандартный метод внедрения OO доставлял меньше проблем, но я мог что-то упустить.
Я рассмотрел концепцию неявной фабрики, но я не могу придать ей форму, чтобы работать с mixins.
РЕДАКТИРОВАТЬ: Удивительно, какую ясность дает публичное написание вопроса. 🙂 Я не решил проблему так, как я изначально предполагал, но есть простое решение реальной проблемы:
trait UsedProvider {
def createUsed = Used.apply _
}
class Main { this: Storage with UsedProvider =>
val used = createUsed(...)
}
Тогда я бы просто сделал следующее в тесте: new Main with StubStorage with StubUsedProvider
.
Ответ №1:
Я тоже не решил вашу первоначальную проблему, но рассматривали ли вы возможность использования абстрактного класса для Main
и предоставления значения для used
там, где оно вам нужно?
abstract class Main { this: Storage =>
val s = "s"
val used: Used
}
Затем создайте экземпляр следующим образом:
val main = new Main with StubStorage { val used = new Used(s) with StubStorage }
Комментарии:
1. Это позволило бы мне создать только один, а мне нужно больше одного, что не было ясно в исходном вопросе. Что мне нужно, так это фабричный метод, который позволяет мне создавать их, когда они мне нужны. Так что я просто снова использую шаблон good ol ‘ cake, чтобы получить эту зависимость.