Inside a function with `where T : CharSequence, T : Comparable<T>`, which members of `T` can you call, and why does combining bounds widen the available API?
answer
- `T` = intersection of bounds, API = union of members
- Comparison operators need the `Comparable` bound
- `length`/`get`/`subSequence` come from `CharSequence`
- No source-level `A & B`; `where` expresses it
- `a < b` desugars to `a.compareTo(b) < 0`
basics
~20 sYou can use every member from all the bounds at once. With CharSequence plus Comparable<T> you get length, indexing, and compareTo/the comparison operators on the same value, because T is effectively the intersection of the bounds.
solid answer
~40 sWithin the body, `T` is treated as the **intersection** of its upper bounds, so the compiler lets you call members declared on **any** of them. With `where T : CharSequence, T : Comparable<T>` you can read `t.length`, use `t[i]` (`CharSequence.get`), call `t.subSequence(...)`, and use `t.compareTo(other)` or the `<`, `>`, `<=`, `>=` operators (which desugar to `compareTo`). That is the practical reason to combine bounds: each one contributes its API, and you need the combination to write logic that both inspects characters and orders values. Without the `Comparable<T>` bound, `a < b` would not compile; without `CharSequence`, `a.length` would not. Because Kotlin lacks first-class intersection types in source, the multi-bound `where` clause is how you say "this value has all of these capabilities simultaneously."
code
kotlin · 10 linesfun <T> clampText(v: T, lo: T, hi: T): T
where T : CharSequence, T : Comparable<T> {
require(lo <= hi) // Comparable
val result = when {
v < lo -> lo
v > hi -> hi
else -> v
}
return result.also { check(it.isNotEmpty()) } // CharSequence (isNotEmpty ext)
}go deeper
Knows members from all bounds become callable on T.
Explains intersection-of-bounds / union-of-members and ties operators like < to the Comparable bound.
Notes Kotlin lacks source intersection types so where is the conjunction mechanism, and explains operator desugaring to compareTo.
Discusses designing APIs around orthogonal capability bounds vs. a single bespoke interface, and the maintainability trade-offs.
## `T` becomes the intersection of its bounds When a parameter has several upper bounds, the compiler reasons about `T` as if it were a value that **implements all of them**. Therefore inside the function you may invoke any member declared on **any** bound — the available API is the **union of members**, because the **type** is the **intersection of bounds**. ```kotlin fun <T> describe(a: T, b: T): String where T : CharSequence, T : Comparable<T> { val longer = if (a.length >= b.length) a else b // CharSequence.length val smaller = if (a < b) a else b // Comparable -> compareTo return "longer=$longer firstOfSmaller=${smaller[0]}" // CharSequence.get } ``` ## Why each bound matters - `CharSequence` contributes `length`, `get(index)` (the `[]` operator), and `subSequence`. - `Comparable<T>` contributes `compareTo(other: T)`, and Kotlin maps the operators `<`, `>`, `<=`, `>=` to it. Remove this bound and `a < b` fails to compile. ## Relation to intersection types Kotlin has no general source-level intersection type syntax (you cannot write `val x: A & B`). The multi-bound `where` clause is the idiomatic way to demand a conjunction of capabilities. (The compiler does use intersection types internally, e.g. for smart casts, but you express required conjunctions through bounds.) ## Practical design value Combining bounds lets one generic function require several **orthogonal capabilities** — "is text" + "is orderable" — without forcing callers through a bespoke wrapper interface. It keeps the function open to any type that already satisfies all the standard interfaces (e.g. `String`). ## Operator desugaring detail `a >= b` compiles to `a.compareTo(b) >= 0`. This only resolves because `Comparable<T>` is in scope via the bound; the operator resolution looks for a `compareTo` returning `Int`.
- If you drop the `Comparable<T>` bound, what breaks?Any use of `<`, `>`, `<=`, `>=`, or `compareTo` on `T` fails to compile, because operator resolution can no longer find a `compareTo`.
- Does Kotlin let you write the type `CharSequence & Comparable<*>` directly in source?No general intersection-type syntax exists for declarations; you express the conjunction through multiple upper bounds in a `where` clause.
Each bound is a tool belt; combining bounds hands the function every tool from every belt at once.
saying these in an interview costs you the question
- Saying you can only call members of the first/last bound
- Believing comparison operators work without a `Comparable` bound
- Claiming Kotlin has source-level `A & B` intersection type syntax for parameters
- Confusing union of bounds with union of members (it is intersection of bounds, union of members)