Скажем, класс A
используется в некотором коде, и я хочу использовать вместо него класс B
, который имеет точно такие же методы, что и класс A
- без B
extension A
. Что было бы самым простым способом go по этому поводу? Другими словами, я ищу простой готовый к использованию и generi c реализацию adaptBtoA
(он должен работать для любых двух классов, имеющих одинаковую структуру / методы).
class A {
def foo(x: String) = "A_" + x
}
class B {
def foo(x: String) = "B_" + x
}
def bar(a: A) = {
// ...
}
bar(adaptBtoA(new B()))
Если вы знакомы с интерфейсами ввода утилит Go, это своего рода семантика, к которой я стремлюсь.
РЕДАКТИРОВАТЬ
Я думаю, что обобщенное решение может быть невозможно из-за стирания типа, хотя я не уверен. Вот моя попытка использования библиотеки mockito
:
def adapt[F, T](impl: F): T = mock[T](new Answer[Any]() {
override def answer(inv: InvocationOnMock): Any =
classOf[T]
.getDeclaredMethod(inv.getMethod.getName, inv.getMethod.getParameterTypes:_*)
.invoke(impl, inv.getArguments:_*)
})
val a: A = adapt[B, A](new B())
val res = a.foo("test") // should be "B_test" but errors in compilation
к сожалению, это не работает, так как я получаю следующую ошибку компилятора:
type arguments [T] conform to the bounds of none of the overloaded alternatives of
value mock: [T <: AnyRef](name: String)(implicit classTag: scala.reflect.ClassTag[T])T <and> [T <: AnyRef](mockSettings: org.mockito.MockSettings)(implicit classTag: scala.reflect.ClassTag[T])T <and> [T <: AnyRef](defaultAnswer: org.mockito.stubbing.Answer[_])(implicit classTag: scala.reflect.ClassTag[T])T <and> [T <: AnyRef](implicit classTag: scala.reflect.ClassTag[T])T
Однако я могу использовать жестко закодированные типы для конкретный c сценарии использования:
def adaptBtoA(b: B): A = mock[A](new Answer[Any]() {
override def answer(inv: InvocationOnMock): Any =
classOf[B]
.getDeclaredMethod(inv.getMethod.getName, inv.getMethod.getParameterTypes:_*)
.invoke(b, inv.getArguments:_*)
})
val a: A = adaptBtoA(new B())
val res = a.foo("test") // res == "B_test"
Если получение информации о типе класса из параметра шаблона во время выполнения невозможно, возможно, я могу использовать макросы для генерации всех необходимых функций adapt
во время компиляции? Тогда код будет выглядеть примерно так:
genAdapt[B, A]()
genAdapt[D, C]()
// etc...
Но я пока недостаточно знаю о scala макросах, чтобы реализовать это, или если это возможно.