Я хочу реализовать шаблон обогащения my-library для внутреннего класса, который будет работать для любого экземпляра внешнего класса. Что-то вроде этого:Обогащение внутреннего класса
class Outer {
class Inner(val x: Option[Inner] = None) {
def test(y: Inner) {}
}
}
implicit class ExtInner(inner: Outer#Inner) {
def get = inner.x.get
}
val outer = new Outer
val inner = new outer.Inner(Some(new outer.Inner))
inner.test(inner.get)
Этот код не будет компилироваться, из-за несоответствия типа: get
возвращает объект типа Outer#Inner
но test
ожидает outer.Inner
.
У меня есть два способа заставить его работать, но оба связаны с использованием asInstanceOf
, которого я бы хотел избежать. Первый из них просто бросить результат get
к outer.Inner
:
inner.test(inner.get.asInstanceOf[outer.Inner])
второй является немного более универсальным и делает кастинг в ExtInner
:
implicit class ExtInner[T <: Outer#Inner](inner: T) {
def get = inner.x.get.asInstanceOf[T]
}
Есть ли лучший способ обогатить внутренний класс, поэтому не нужно делать кастинг?
Pimp my library pattern предполагает, что класс 'Outer' не может быть изменен, поэтому использование' ExtInner' внутри класса 'Outer' на самом деле не является решением. Если 'ExtInner' принимает' external.Inner' вместо 'Outer # Inner', привязывает его к конкретному экземпляру, что нежелательно, потому что нам нужно будет определить новое неявное преобразование для каждого экземпляра класса' Outer'. – gleb
Тогда вы должны принять мой третий ответ, что вы не можете получить неявное применение. Это аналогично преобразованию регулярных выражений в мини-торт Parsers, поэтому он должен быть обычным прецедентом. Там всегда есть отражение и макросы. –
Ваш третий ответ выполняет работу без кастинга, хотя для этого требуется немного кода шаблона. Можете ли вы прокомментировать, почему нам нужно «с Синглтоном», похоже, он работает без него? – gleb