Function subtyping variance 2026-10-24
If and , a function of type safely supplies a contract of type . Every input permitted by the new contract is already accepted, and every possible returned value meets the weakened result promise. This proves contravariance of inputs and covariance of outputs. Reversing either direction can respectively supply an unsupported input or promise a result more specific than the implementation returns. A language's generic type object constructor may nevertheless be invariant unless its declaration exposes the appropriate variance.
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