You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/src/md/kotlin.core/overload-resolution.md
+76-11Lines changed: 76 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -621,12 +621,22 @@ TODO(Explain why anonymous function declarations DO NOT have a defined type w.r.
621
621
> }
622
622
> ```
623
623
624
-
### Resolving properties
624
+
### Resolving property access
625
625
626
626
As [properties][Property declaration] in Kotlin can have custom [getters and setters], be [extension][Extension property declaration], [delegated][Delegated property declaration] or [contextual][Contextual property declaration], they are also subject to overload resolution.
627
-
Overload resolution for properties works similarly to how it works for [callables][Callables and `invoke` convention], i.e., it consists of two steps: [building the overload candidate set] of [applicable][Determining function applicability for a specific call] candidates, and then [choosing the most specific candidate from the overload candidate set].
627
+
Overload resolution for property access works similarly to how it works for [callables][Callables and `invoke` convention], i.e., it consists of two steps: [building the overload candidate set] of [applicable][Determining function applicability for a specific call] candidates, and then [choosing the most specific candidate from the overload candidate set].
628
628
629
-
Informally, access to a property is resolved as if it is a callable invocation corresponding to its getter or setter, and the overload resolution is performed on this invocation.
629
+
> *Important*: this section concerns *only* properties accessed using property access syntax `a.x` or just `x` *without call suffix*.
630
+
> If a property is accessed with a call suffix, it is treated as any other callable and is required to have a suitable `invoke` overload available, see the rest of this part for details
631
+
632
+
There are two variants of property access syntax: readonly property access and property assignment.
633
+
634
+
> Note: there is also [safe navigation syntax][Navigation operators] for both assignment and readonly access, but that is expanded to non-safe navigation syntax covered by this section.
635
+
> Please refer to corresponding sections for details.
636
+
637
+
Readonly property access `a.x` is resolved the same way as if the property access in question was a special function call `a.x$get()` and each property `val/var x: T` was replaced with corresponding function `fun x$get(): T` having all the same extension receivers, context receivers, type parameters and scope as the original property and providing direct access to the property getter.
638
+
For different flavors of property declarations and getters, refer to [corresponding section][Property declaration].
639
+
Please note that this excludes any possibility to employ `invoke`-convention as these ephemeral functions cannot be properties themselves.
630
640
631
641
> Example: one may consider property access in class `A` to be resolved as if it has been transformed to class `AA`.
632
642
>
@@ -652,19 +662,75 @@ Informally, access to a property is resolved as if it is a callable invocation c
652
662
>
653
663
> ```kotlin
654
664
> class AA {
655
-
> fun a(): Int = 5 // (1)
665
+
> fun a$get(): Int = 5 // (1)
656
666
>
657
-
> fun Double.a(): Boolean // (2)
667
+
> fun Double.a$get(): Boolean // (2)
658
668
> = this != 42.0
659
669
>
660
670
> fun test() {
661
671
>
662
-
> println(a()) // Resolves to (1)
672
+
> println(a$get()) // Resolves to (1)
673
+
>
674
+
> with(42.0) {
675
+
> println(this@AA.a$get()) // Resolves to (1)
676
+
> println(this.a$get()) // Resolves to (2)
677
+
> println(a$get()) // Resolves to (2)
678
+
> }
679
+
> }
680
+
> }
681
+
> ```
682
+
683
+
Property assignment `a.x = y` is resolved the same way as if it was replaced with a special function call `a.x$set(y)` and each property `var/val x: T` was replaced with a corresponding function `fun x$set(value: T)` having all the same extension receiver parameters, context receiver parameters, type parameters and scope as the original property and providing direct access to the property setter.
684
+
For different flavors of property declarations and setters, refer to [corresponding section][Property declaration].
685
+
Please note that, although a readonly property declaration (using the keyword `val`) does not allow for assignment or having a setter, it still takes part in overload resolution for property assignment and may still be picked up as a candidate.
686
+
Such a candidate (in case it is selected as the final candidate) will result in compiler error at later stages of compilation.
687
+
688
+
> Note: informally, one may look at property assignment resolution as a sub-kind of readonly property resolution described above, first resolving the property as if it was accessed in a readonly fashion, and then using the setter.
689
+
> Readonly property access and property assignment syntax used in the same position **never** resolve to different property candidates
690
+
691
+
> Example: one may consider property access in class `B` to be resolved as if it has been transformed to class `BB`.
692
+
> Declaration bodies for ephemeral functions are ommited to avoid confusion
693
+
>
694
+
> ```kotlin
695
+
> class B {
696
+
> var b: Int = 5 // (1)
697
+
>
698
+
> val Double.b: Int // (2)
699
+
> get() = this.toInt()
700
+
>
701
+
> fun test() {
702
+
> b = 5 // Resolves to (1)
703
+
>
704
+
> with(42.0) {
705
+
> // Resolves to (1)
706
+
> this@B.b = 5
707
+
> // Resolves to (2) and compiler error: cannot assign readonly property
708
+
> this.b = 5
709
+
> // Resolves to (2) and compiler error: cannot assign readonly property
710
+
> b = 5
711
+
> }
712
+
> }
713
+
> }
714
+
> ```
715
+
>
716
+
> ```kotlin
717
+
> class BB {
718
+
> fun b$get(): Int // (1, getter)
719
+
> fun b$set(value: Int) // (1, setter)
720
+
>
721
+
> fun Double.b$get(): Int // (2, getter)
722
+
> fun Double.b$set(value: Int) // (2, setter)
723
+
>
724
+
> fun test() {
725
+
> b$set(5) // Resolves to (1)
663
726
>
664
727
> with(42.0) {
665
-
> println(this@AA.a()) // Resolves to (1)
666
-
> println(this.a()) // Resolves to (2)
667
-
> println(a()) // Resolves to (2)
728
+
> // Resolves to (1)
729
+
> this@B.b$set(5)
730
+
> // Resolves to (2)
731
+
> this.b$set(5)
732
+
> // Resolves to (2)
733
+
> this.b$set(5)
668
734
> }
669
735
> }
670
736
> }
@@ -674,8 +740,7 @@ The overload resolution for properties has the following features distinct from
674
740
675
741
* Properties without getter or setter are assumed to have default implementations for accessors (ones which get or set its [backing field][Getters and setters]);
676
742
* The overload resolution takes into account the kind of property, meaning an extension read-only property is considered to have an extension getter, a contextual mutable property is considered to have a contextual getter and setter, etc.;
677
-
* When building the overload candidate set, only candidates which are property getters and setters are considered;
678
-
> Note: this means `invoke` operator convention cannot take part in _property_ overload resolution.
743
+
* [Object declarations][object declaration] and [enumeration entries][Enum class declaration] may be accessed using the property access syntax given that they may be resolved in the current scope.
0 commit comments