For a value of type Array<out Number>, which Array members can you call and which are forbidden, and why?
answer
- out → get OK, set blocked
- set's value projected to Nothing
- size/iterator always fine (no T)
- in → set OK, get returns Any?
- compiler checks in/out position of T
basics
~10 sYou can read: get returns Number, and size works. You cannot call set, because the real element type is unknown and writing a Number could be wrong. Out makes it read-only for elements.
solid answer
~40 sWith Array<out Number>, the type parameter is projected covariantly, so only members where T appears in an out (return) position stay callable with their normal types. get(index): Number works, size and indices work, iterator() works. Members where T is in an in (parameter) position become restricted: set(index, value: T) is effectively typed as set(index, value: Nothing), so you can never supply a real argument and the compiler rejects any set call. The reason: the actual array might be Array<Int>; allowing set(i, someNumber) could store a non-Int into an Int array. The compiler enforces this statically, not at runtime. fill(fromIndex, toIndex, element: T) is similarly blocked because element is an in-position. So Array<out Number> is a read-only-elements view even though the underlying object is fully mutable.
code
kotlin · 8 linesfun sumFirst(a: Array<out Number>): Double {
val first: Number = a[0] // get allowed
// a[0] = 0.0 // compile error: value projected to Nothing
return first.toDouble()
}
sumFirst(arrayOf(1, 2, 3)) // Array<Int> ok
sumFirst(arrayOf(1.5, 2.5)) // Array<Double> okgo deeper
Knows out allows reads and blocks writes on the array.
Maps in/out positions of T to which members survive and names get vs set precisely.
Explains the value parameter is projected to Nothing and why that statically blocks set.
Articulates the soundness model: projection restricts the API surface to the variance-safe subset to preserve type safety on a mutable type.
## How projection maps to member availability Kotlin decides which members survive a projection by looking at **where the type parameter `T` appears** in each member's signature: - **out position** (return type): safe under `out` projection — kept as-is. - **in position** (parameter type): unsafe under `out` projection — the parameter is projected to `Nothing`, making the member effectively uncallable. For `Array<T>` the relevant members are: ```kotlin operator fun get(index: Int): T // T is OUT (return) operator fun set(index: Int, value: T) // T is IN (parameter) val size: Int // no T ``` ## Under Array<out Number> ```kotlin fun inspect(a: Array<out Number>) { val n: Number = a[0] // OK: get(): Number val s = a.size // OK: no T involved for (x in a) println(x) // OK: iterator/get // a[0] = 1 // ERROR: set's value is projected to Nothing } ``` `a[0]` returns `Number` — perfectly usable. But `a[0] = 1` fails to compile. The compiler treats `set` as if its signature were `set(index: Int, value: Nothing)`, and **nothing except `Nothing` itself** (which has no instances) can be passed, so every `set` call is rejected. ## Why `Nothing`? `Nothing` is Kotlin's bottom type — a subtype of every type with no values. Projecting the consumed `T` to `Nothing` is the formal way the compiler says "there is no value you could safely write here", because the real element type is some unknown subtype of `Number`. ## Contrast with Array<in Number> The mirror image: `set(index, value)` accepts `Number` (and subtypes like `Int`), but `get` is projected so its return type becomes `Any?` — you lose the precise read type. So `out` = read precisely / no write; `in` = write `Number` / read only as `Any?`. ## Practical takeaway `Array<out Number>` is the idiomatic way to declare a parameter you only read element-wise. It documents intent and lets callers pass `Array<Int>`, `Array<Double>`, etc.
- What exactly is the inferred type of the value parameter of set under Array<out Number>?It is projected to Nothing. Since Nothing has no instances, no argument satisfies it, so set is uncallable.
- Does the projection change runtime behavior of the array object?No. The underlying array is still fully mutable; projection is a compile-time view restriction only.
saying these in an interview costs you the question
- Saying set just throws at runtime instead of being a compile error
- Claiming size becomes unavailable under projection
- Thinking get returns Any? under out (it returns Number)
- Not mentioning Nothing as the projected parameter type
- Believing the array becomes immutable for everyone, not just through this view