| // TARGET_BACKEND: JVM | |
| // WITH_STDLIB | |
| // FILE: A.java | |
| public class A { | |
| private String[] myStrings = null; | |
| public A withStrings(String... args) { | |
| myStrings = args; | |
| return this; | |
| } | |
| public String[] getStrings() { | |
| return myStrings; | |
| } | |
| } | |
| // FILE: B.java | |
| public class B { | |
| private String[] myStrings = null; | |
| public B withStrings(String... args) { | |
| myStrings = args; | |
| return this; | |
| } | |
| public String[] getStrings() { | |
| return myStrings; | |
| } | |
| } | |
| // FILE: main.kt | |
| class ListsMerger<SRC, TRG, VAL>( | |
| private val sourceGetter: (SRC) -> List<VAL>?, | |
| private val targetGetter: (TRG) -> List<VAL>?, | |
| private val setter: (TRG, List<VAL>) -> Any | |
| ) { | |
| fun mergeLists(source: SRC, target: TRG) { | |
| val fromSource = sourceGetter(source) | |
| val existing = targetGetter(target) | |
| val result: List<VAL> = (fromSource ?: emptyList()) + (existing ?: emptyList()) | |
| setter(target, result) | |
| } | |
| } | |
| inline fun <SRC, TRG, reified VAL> mergeArrays( | |
| source: SRC, | |
| target: TRG, | |
| crossinline sourceGetter: (SRC) -> Array<VAL>?, | |
| crossinline targetGetter: (TRG) -> Array<VAL>?, | |
| crossinline setter: (TRG, Array<VAL>) -> Any | |
| ) { | |
| ListsMerger<SRC, TRG, VAL>( | |
| sourceGetter = { sourceGetter(it)?.toList() }, | |
| targetGetter = { targetGetter(it)?.toList() }, | |
| setter = { trg, list -> setter(trg, list.toTypedArray()) } | |
| ).mergeLists(source, target) | |
| } | |
| fun box(): String { | |
| val a = A().withStrings("a", "b", "c") | |
| val b = B().withStrings("d", "e") | |
| mergeArrays(a, b, A::getStrings, B::getStrings, B::withStrings) | |
| val merged = b.getStrings().contentToString() | |
| return if (merged == "[a, b, c, d, e]") "OK" else "FAIL $merged" | |
| } |