Solution (source code)

= Solution

<Scala trait linearization> merges parent linearizations from right to left, deleting an earlier occurrence when that same ancestor occurs in a later appended parent linearization. Each class precedes its ancestors, and an ancestor appears once.<Scala 2.13 classes and objects specification>[Class Linearization: concatenation replaces identical elements of its left operand with their occurrences in the right operand; the same rule is used for the Scala 2 code here]{ref} Ignoring the predefined roots gives

|| Type
|| Linearization, most specific first

| `K`
| `K`

| `I`
| `I, K`

| `J`
| `J, K`

| `G`
| `G, I, K`

| `F`
| `F, J, I, K`

| `H`
| `H, J, K`

| `D`
| `D, F, J, G, I, K`

| `E`
| `E, H, J, K`

| `A`
| `A, D, F, J, G, I, K`

| `B`
| `B, E, H, D, F, J, G, I, K`

| `C`
| `C, E, H, J, K`

Each override appends its letter after `super.m` returns. Reading the method chain in reverse from `K` therefore yields the three output lines:

``
KIGJFDA
KIGJFDHEB
KJHEC
``

In particular, mixing `H` into `C` again does not create another `H` or move it before its subclass `E`. Also, `J` lies between `F` and `G` in `D`'s chain; `super` follows the final linearization, not simply one statically named parent.