То, что я хотел бы достичь, - это правильная реализация для
def dynamix[A, B](a: A): A with B
Я знаю, что такое B, но не знаю, что такое A (но если B имеет тип self, то я мог бы добавить некоторые ограничения на A). Компилятор scala доволен вышеупомянутой подписью, но я еще не мог понять, как будет выглядеть реализация - если это вообще возможно.
Некоторые варианты, которые пришли мне на ум:
- Использование отражения/динамического прокси.
- Простейший случай: A - это интерфейс на уровне Java +, я могу создать экземпляр B, и он не имеет типа self. Думаю, это было бы не слишком сложно (если не натолкнуться на какие-то неприятные, неожиданные проблемы):
создать новый B (b), а также прокси-сервер, реализующий как A, так и B, и используя обработчик вызова, делегирующий либо a, либо b. - Если B не может быть создан, я все равно могу создать его подкласс и сделать, как описано выше. Если он также имеет тип "я", мне, вероятно, понадобится некоторая делегация здесь и там, но он все равно может работать.
- Но что, если A - конкретный тип, и я не могу найти для него подходящий интерфейс?
- У меня возникли бы проблемы (например, что-то связанное с линеаризацией или специальные конструкции, помогающие взаимодействию Java)?
- Простейший случай: A - это интерфейс на уровне Java +, я могу создать экземпляр B, и он не имеет типа self. Думаю, это было бы не слишком сложно (если не натолкнуться на какие-то неприятные, неожиданные проблемы):
- Используя вид обертывания вместо mixin и return B [A], a доступен из b.
К сожалению, в этом случае вызывающему нужно было бы знать, как выполняется вложение, что может быть весьма неудобным, если перемешивание в/обертывание выполняется несколько раз (D [C [B [A]]]), поскольку ему нужно будет найти правильный уровень вложенности для доступа к необходимой функциональности, поэтому я не считаю это решением. - Реализация плагина компилятора. У меня с ним нет опыта, но я чувствую, что это не будет тривиально. Я думаю, что Кевин Райт autoproxy плагин имеет немного схожую цель, но этого было бы недостаточно для моей проблемы (пока?).
Есть ли у вас какие-либо другие идеи, которые могут работать? В каком направлении вы порекомендовали бы? Какие "вызовы" можно ожидать?
Или я должен забыть об этом, потому что это невозможно с текущими ограничениями scala?
Намерение за моей проблемой:
Скажем, у меня есть рабочий процесс, но он не слишком строгий. Некоторые шаги имеют фиксированный порядок, но другие нет, но в конце все они должны быть выполнены (или некоторые из них необходимы для дальнейшей обработки).
Немного более конкретный пример: у меня есть A, я могу добавить B и C к нему. Мне все равно, что делается первым, но в конце мне понадобится A с B с C.
Комментарий: я не слишком много знаю о Groovy, но SO выскочил этот вопрос, и я думаю, что это более или менее то же, что и я как, по крайней мере, концептуальный.