Перегрузка функции в kotlin по реальному типу аргумента
По заголовку, скорее всего, будет сложно понять, о чём вопрос. Сейчас попытаюсь разъяснить на примере.
Допустим у нас есть интерфейс и несколько классов, которые его реализуют:
sealed interface IMyIntf
class MyClassA: IMyIntf
class MyClassB: IMyIntf
class MyClassC: IMyIntf
Теперь допустим, что у нас есть функции, каждая из которых принимает на вход один из этих классов. Так же допустим, что все эти функции являются расширениями к некоторому классу, который мы назовём class MyEnviroment. В данном случае важно не то, что конкретно он делает, а то, что он не даёт реализовать данные функции, как расширения к MyClassA, MyClassB и MyClassC, потому как это место уже занято MyEnviroment.
fun MyEnviroment.func(a: MyClassA) {/*какой-то код*/}
fun MyEnviroment.func(b: MyClassB) {/*какой-то код*/}
fun MyEnviroment.func(c: MyClassC) {/*какой-то код*/}
Задача: сделать такую функцию func, которая получала бы на вход аргумент типа IMyIntf и перенаправляла бы вызов в реализацию func, с соответствующим типом аргумента.
На текущий момент я использую для решения данной задачи такой подход:
fun MyEnviroment.func(intf: IMyIntf) = when(intf) {
is MyClassA -> func(intf)
is MyClassB -> func(intf)
is MyClassC -> func(intf)
}
Но он имеет целый ряд недостатков, не считая того, что это просто костыль,:
- Метод требует постоянного дополнения, при добавлении новых наследников у
IMyIntf. - Много совершенно однотипной копипасты. Особенно, если наследников у
IMyIntfбудет много. - Для упрощения кода никак не используется тот факт, что
IMyIntf- естьsealed interface, хотя если закопаться глубоко в рефлексию, то что-то на эту тему сварганить, конечно же, можно. Но рефлексия - это такое ЗЛО, к которому без крайней необходимости прибегать не хочется. - Просто выглядит некрасиво, как по мне.
Собственно хотелось бы узнать, вдруг в языке есть какие-то фокусы, которые позволили бы описать такую функцию один раз и навсегда, но желательно, без рефлексии и прочей опасной бяки.