Companion object 2026-10-31
In Scala, a singleton object associated with a same-named companion class in the required source context. Object members and instance members are distinct:
B.g(x) invokes a member of object B, while b.g(x) invokes an instance member through b. Both can use method overloading, but the instance's members are not automatically part of the companion's overload set.[ref]Write each Scala trait linearization from most specific to least specific. Merge the parents' Scala trait linearizations right-to-left, removing a duplicate from the earlier portion when it also appears in the later portion. This retains every base once while respecting its required position after derived traits.[ref]For example, combining the final
CityMan, City, Earth, Man, Mammal, Animal, Describe
BirdMan, City, Earth, Man, Mammal, Bird, Animal, Describe
BatMan, Man, Gotham, City, US, Earth, Bat, Mammal, Bird, Animal, DescribeCity with Gotham does not put City before its derived trait Gotham; duplicate removal places it after Gotham. Similarly Mammal and Bird remain after Bat, despite their occurrence through other parents.Each Each line has a final comma and space, because every printed string fragment includes them. The essential result is
describe calls super.describe before appending its own label. Thus execution enters implementations along the displayed Scala trait linearization, and appends labels in reverse order when calls return. The three printed lines areDescribe, Animal, Mammal, Man, Earth, City,
Describe, Animal, Bird, Mammal, Man, Earth, City,
Describe, Animal, Bird, Mammal, Bat, Earth, US, City, Gotham, Man, List each Scala trait linearization from the most specific software class toward the common base, omitting predefined types:For example,
Life1, Party, Study, Life
Life2, Sport, Exercise, Research, Party, Study, Life
Life3, Research, Study, Sport, Party, Exercise, LifeSport alone linearizes as Sport, Party, Exercise, Life, while Research alone gives Research, Party, Study, Life. In combining parents, take the right parent's linearization first, deleting from it entries also present in the remaining left-parent linearization, then append the latter. This places a common base after all of its derived traits.[ref]An unqualified The first three lines belong to
super.describe() continues after the current trait in the actual receiver's Scala trait linearization. Each override prints after its super call, so the output follows the displayed order backwards, starting at Life. The complete output is:I live.
More on study.
More on party.
I live.
More on study.
More on party.
More on research.
More on exercise.
More on sport.
I live.
More on exercise.
More on party.
More on sport.
More on study.
More on research.l1, the next six to l2, and the final six to l3.Maintain one frequency count for each lowercase alphabet character. Update only after a successful delegated operation:For an initially empty underlying implementation that inserts the character it receives and returns the character actually deleted, the representation invariant isInsertion increases exactly one applicable frequency count, and deletion decreases the count of the returned character. Uppercase and nonletter characters contribute nothing. Exceptions from failed underlying operations leave the counters unchanged. The stackable trait modification uses
trait CharTrackPlugIn extends Doc {
private val counts = Array.fill[Int](26)(0)
private def lower(x: Char): Boolean = 'a' <= x && x <= 'z'
abstract override def insert(x: Char, pos: Int): Unit = {
super.insert(x, pos)
if (lower(x)) counts(x - 'a') += 1
}
abstract override def delete(pos: Int): Char = {
val old = super.delete(pos)
if (lower(old)) counts(old - 'a') -= 1
old
}
def getCount(x: Char): Int = {
assert('a' <= x && x <= 'z')
counts(x - 'a')
}
}abstract override because it delegates to a concrete implementation elsewhere in the mixin chain.[ref]The counters depend on the character seen by this trait. A later trait that transforms characters can break the stated underlying-operation assumption; part (d) deliberately exposes that order dependence.Read each Scala trait linearization from the most specific implementation toward the base. For a declaration with parents , concatenate their linearizations from right to left, deleting a duplicate from a left operand when it already occurs in the right operand. This can move a repeated ancestor later than a superficial “rightmost trait first” scan suggests. Omitting the common For example,
AnyRef, Any suffix, the answers areC, Y, H, N, L, I, E
B, Y, H, N, L, D, I, E
A, N, O, Y, S, H, T, L, D, I, ET contributes T,L,D,I,E, while O contributes O,Y,S,H,E. In A, the separately mentioned Y also appears in the later merge with O, and N's ancestors also occur in T; resolving these duplicates yields the final order displayed above. The inherited trait orders are the displayed lists after removing their leading class names. [ref]The output becomes
BCA, without a newline. Here each method body consists only of super.m; the semicolon ends that definition. The following print("B") or print("C") is a separate statement in the trait body, so it executes during construction.Creating
new D initializes the shared base and then the B and C mixins, printing BC. The subsequent d.m still forwards along C,B,A, but only A.m now prints anything, appending A. Thus it is the placement of the construction-time statements, not a changed Scala trait linearization, that changes the output. [ref]