I have a set of component interfaces
interface ITest<I> { operator fun invoke(p: I) } interface OTest<O> { operator fun invoke(): O } interface IOTest<I, O> { operator fun invoke(p: I): O } and a corresponding functional interface
interface TestAdder<T> { fun add_f(p: T) {} //default impl } that gets inherited to add the components from above to respective (functional) collection interfaces
interface ITestSet<I> : TestAdder<ITest<I>> { val i_v: I fun i_f1(p: I) {} // default impl fun i_f2(p: I) {} // default impl fun i_f3(p: I) {} // default impl } interface OTestSet<O> : TestAdder<OTest<O>> { val o_v: O fun o_f1(p: O) {} // default impl fun o_f2(p: O) {} // default impl fun o_f3(p: O) {} // default impl } interface IOTestSet<I, O> : TestAdder<IOTest<I, O>> { val i_v: I val o_v: O // same as ITestSet<I> fun i_f1(p: I) {} // default impl fun i_f2(p: I) {} // default impl fun i_f3(p: I) {} // default impl // same as OTestSet<O> fun o_f1(p: O) {} // default impl fun o_f2(p: O) {} // default impl fun o_f3(p: O) {} // default impl fun io_f1(p: I): O ... } So far, so unnecessay: ideally IOTestSet<I, O> should inherit the functionality defined in ITestSet<I> and OTestSet<O>:
interface IOTestSet<I, O> : ITestSet<I>, OTestSet<O>, TestAdder<IOTest<I, O>> { fun io_f1(p: I): O ... } but obviously the TestAdder<T> interface introduces inconsistency within the inheritance chain.
This smells like an age-old, archetypal paradigm (and probably even an XY) problem, still it seems I have to ask:
add_fmethod ofIOTestSetgoing to take?ITest<I>,OTest<O>, orIOTest<I, O>? If you want overloads for all types to exist, inheritance won't work here because, (long story short) type erasure.f_addfunction on all[IO|I|O]TestSetinterfaces accepting their respectiveIO|I|O]Testinterfaces. I guess I could externalize the[i_|o_}f<n>functionality into yet another set of Interfaces, inherit them and have a specificadd_fmethod on allTestSets. Any other way you can think of to redesign?