2017-01-31 12 views
0

Я работаю над существующей базой кода с классом оболочки вокруг Slick 2.1.0 (я знаю). Эта оболочка имеет метод с именем transaction, который является общим - он принимает (f: => T) (так что это пропуск-по-имени). Мне нужно высмеять этот класс для модульного теста. Мы также используем Mockito 1.10.19 (опять же, я знаю), что не позволит мне издеваться над пропущенным именем (я считаю ...). Поэтому я застрял в реализации базового признака, на котором построен этот класс-оболочка.Как обеспечить специализированные реализации общих методов в Scala?

Непосредственная проблема заключается в следующем: я хочу издеваться над этим методом transaction, чтобы он ничего не делал. Код, который я тестирую, проходит в (f: => Unit). Поэтому я хочу реализовать этот метод, чтобы вернуть Future.Done. (Я упоминал, что мы используем фьючерсы Finagle, а не Scala?) Но этот метод является общим. Как я правильно специализируюсь?

Это моя текущая попытка:

Конечно, я получаю ошибку have same type after erasure при компиляции. Очевидно, я не знаю, как работает @specialized.

Что мне делать? Может быть, я могу использовать Mockito? Или мне нужно узнать, что на самом деле означает специализированный метод?

Я нашел, что, вероятно, содержит ответ, но у меня нет никакого формального фона в FP, и я не обращал внимания на это вообще: How can one provide manually specialized implementations with Scala specialization?

+0

Зачем вам нужно специализироваться? Не переопределяет ли метод 'transcation' на' DatabaseManager' достаточно для достижения того, что вы хотите? –

+0

Мне пришлось попробовать еще раз, потому что я задаю себе вопрос об этом. Сам признак определяет общий метод. Мне нужно переопределить его собственным родовым. Но я могу вернуть «Future.Done» только в том случае, если общий тип «Unit». Отсюда и специализация. Я уверен, что я что-то упустил. Что это? – alyssackwan

+0

Итак, вы хотите 'Future.Done' вместо' Future.value (Unit) '? –

ответ

2

@specialized не позволяет обеспечить специализаций, он просто генерирует свой. Ответ, указанный в связанном вопросе, потребует изменения подписи. Из вопроса, похоже, вы не можете его изменить, и в этом случае вам не повезло. Если вы можете ... вам все равно не повезло, в зависимости от того, как именно этот код будет вызван.

OTOH, решение для «Я хочу, чтобы игнорировать f, но может возвращать только Future.Done если генерик для Unit типа» гораздо проще:

class Default[A] { 
    var x: A = _ 
} 
object Default { 
    def apply[A]() = (new Default[A]).x 
} 

val mockDBM = new DatabaseManager { 
    override def transaction[T](f: => T): Future[T] = { 
    Future.value(Default(x)) 
    } 
} 

Предполагая, что вы нуждаетесь в успешное будущее, но дон не заботьтесь о ценности, то есть; если вам просто нужно любое будущее, override def transaction[T](f: => T): Future[T] = Future.???.

+0

OMG. Я скоро буду в офисе и попробую это, но что тут подчеркивает нижеследующее? – alyssackwan

+0

Нет кубиков. Запуск Scala 2.11.7. Я получаю «локальные переменные должны быть инициализированы». С 'val' вместо' var' я получаю 'unbound placeholder parameter'. :( – alyssackwan

+0

А, правильно, это можно сделать только в поле. Исправлено. –