Inside a class, how does an infix member function bind to `this`, and what subtle issue arises when you call an infix member from within the same class without specifying a receiver?
answer
- Infix member receiver = the class instance
- Inside the class use `this name arg`, not bare `name arg`
- `name(arg)` parens form always works
- Member infix beats same-name extension infix
- When unsure: `this.name(arg)`
basics
~20 sAn infix member's left operand is its receiver. If you call it inside the class without a left operand, you must write this name arg explicitly — bare name arg doesn't work, because infix needs an explicit left side.
solid answer
~40 sFor an infix member `infix fun add(x: Int)`, the call `obj add 5` uses `obj` as the receiver. Inside the same class, `this` is the implicit receiver for normal `.` calls, but the infix form **requires an explicit left operand** — you must write `this add 5`, not `add 5` (which the parser reads as a regular call `add(5)` only if you supply parens, i.e. `add(5)`). So within a member you typically call it as `this add 5` or fall back to `add(5)`. A second subtlety: when an infix member and an infix extension with the same name are both in scope, the **member wins** (member resolution precedence), which can shadow an imported extension unexpectedly. Always know which receiver and which declaration the infix call resolves to.
code
kotlin · 10 linesclass Counter(val n: Int) {
infix fun plusN(m: Int): Counter = Counter(n + m)
fun doubled(): Counter {
// return plusN n // compile error: infix needs explicit left operand
return this plusN n // works
}
}
val c = Counter(2) plusN 3 // receiver Counter(2), arg 3 -> Counter(5)go deeper
Knows the left operand is the receiver and that obj name arg works at a call site.
Understands that inside the class you need this name arg and that name(arg) always works.
Explains member-over-extension resolution and the shadowing risk between same-named infix declarations.
Anticipates resolution/shadowing hazards in API evolution and prescribes explicit this.name(arg) for clarity in shared codebases.
## Receiver binding An infix function always has a **receiver** (the left operand). For a **member** function the receiver is the enclosing class instance: ```kotlin class Vec(val x: Int) { infix fun add(other: Int): Vec = Vec(x + other) } val v = Vec(1) add 5 // receiver = Vec(1), arg = 5 ``` ## Calling an infix member from inside the class Inside a member of `Vec`, `this` is the implicit receiver. But the **infix call form needs an explicit left operand** — you can't drop it: ```kotlin class Vec(val x: Int) { infix fun add(other: Int): Vec = Vec(x + other) fun grow(): Vec { // return add 5 // does NOT compile as infix — no left operand return this add 5 // OK: explicit receiver // return add(5) // OK: ordinary call form } } ``` The takeaway: **`this` is implicit for `.`/parens calls but must be explicit for infix syntax.** ## Member-vs-extension resolution If both an infix **member** and an infix **extension** with the same name are in scope, Kotlin resolves to the **member** (members take priority over extensions). This can silently shadow an imported extension: ```kotlin class Box { infix fun combine(o: Box): Box = this // member } infix fun Box.combine(o: Int): Box = this // extension, different param type // `box combine box2` -> member; `box combine 3` -> extension (by arg type) ``` When the signatures differ only by receiver/specificity, the member generally wins for matching argument types — be deliberate. ## Why it matters - Infix syntax is sugar, but the **explicit left operand** requirement inside a class trips people who expect implicit-`this` behavior. - Shadowing between member and extension infix functions can change which code runs without a compile error. - When unsure, use the unambiguous `this.name(arg)` form.
- If a class has an infix member and an import brings an infix extension of the same name, which is called?The member takes precedence over the extension when the argument matches both; the extension is shadowed. Differing parameter types can route calls to the extension instead.
- Can you write `add 5` (no receiver) inside the class to invoke the infix member?No. Infix syntax requires an explicit left operand, so you write `this add 5`, or use the ordinary `add(5)` call form.
saying these in an interview costs you the question
- Assuming bare `name arg` works inside the class via implicit `this`
- Thinking extension infix functions override member ones
- Not realizing infix needs an explicit left operand
- Believing infix changes receiver resolution rules
- Ignoring shadowing between member and extension infix declarations