Count each invocation before delegating, including duplicate insertions, and reset after clearing:
class IntegerSetWithCount extends IntegerSet() {
private var attempts = BigInt(0)
override def insert(x: Int): Unit = {
attempts += 1
super.insert(x)
}
override def clear: Unit = {
super.clear
attempts = BigInt(0)
}
def getCount: BigInt = attempts
}The inherited implementation already maintains
size; the new counter measures insertion attempts, not successful increases in cardinality. Deletion and popping do not subtract from it. Incrementing before delegation also counts an attempted insertion that subsequently fails a capacity check. Arbitrary-precision arithmetic avoids silently wrapping the historical count, though its arithmetic is not constant-cost for arbitrarily large counts.As the source supplies no object constructor signature for the concrete set, this code uses a fresh default-constructible
IntegerSet, with matching default capacity. Its correct behavior also assumes the base implementation does not internally invoke these overridable operations in a way that interferes with the counter. Part e exhibits that dependency.Source-signature qualification for the following set implementations: the intended membership query must be declared
def contains(x: Int): Boolean. The printed abstract declaration omits its result type; interpreted literally as Scala 2 procedure syntax, it returns Unit. The solutions use the explicit Boolean query contract, and Unit for the two mutators. Parameterless clear is overridden without adding parentheses.[ref]Scala 2.13 basic declarations and definitions specification. Procedures: a method declaration omitting its result type implicitly has Unit result
Give the two components independent upper type bounds and immutable fields:
final case class BoundedPair[+A <: Base, +B <: Base](first: A, second: B)Each component type must be a subtype of
Base, but the two need not be the same subtype. The pair's fields cannot be reassigned. Their read-only use permits covariant type parameters; the separate upper type bounds constrain admissible instantiations.[ref]Scala 2.13 basic declarations and definitions specification. Type Parameters and Variance Annotations: upper bounds restrict admissible arguments; immutable output positions permit covariance
The component accessors retain their precise static types. For example, a
BoundedPair[Derived, Base] exposes its first component as Derived, so derived-specific operations are available without a cast. A pair whose two fields are simply declared Base discards that distinction. Immutability here concerns the two stored references; it does not guarantee that the referenced software objects have immutable internal state.