Xiaodi, thank you.
I do not doubt what you've written. But, please indulge me for a moment, as I'm exploring this behavior in the larger context of trying to understand protocol conformance behaviors.
Are you aware of any formal documentation of this overriding behavior? The only documentation that I've found is this note in the introduction to the Extension chapter of The Swift Programming Language (maybe I've not been diligent in my search):
NOTE
Extensions can add new functionality to a type, but they cannot override existing functionality.
I would've thought that that note was speaking to this situation, among others. [I also observe that, in light of the ability to provide conditional conformances in extensions, that note is not entirely accurate.]
From a distance, I've assumed the following about the interrelationship between modules vis a vis types:
(A) VENDORS POV. The burden would be on the vendor of a module, first and foremost, (1) to not engage in the practice of publicly extending types that originate outside their module; (2) when they break rule (1), to prominently and clearly document it; and (3) when they alter the API of types that originate in their module, to prominently and clearly document it.
(B) VENDEE'S POV. The burden would be on the vendee of a module, first and foremost, (1) if extending a type originating in the module, to take care to not choose member names that conflict, or are likely to conflict, with the type's module-provided API, and (2) just in case the vendor might change the type's API in a way that conflicts with the vendee's extension, to be fully prepared to update the vendee's program to adjust to the API change. I observe that doing (2) is really no different than the vigilance and effort required to use any module outside of one's own control and that the need to do (2) it is totally avoidable.
(C) EDGE AND CORNER CASES. In the (I think) unusual case of two modules both extending the same type with the same member name and then publicly vending that type (e.g., modules A and B both extend Array<T> where T: Comparable
to provide an isOrdered
property), with a third module importing both of those modules and using the conflicting type, I suppose the owner of the third module could deal with the conflict by never calling the conflicting member, and instead creating some different member name to provide the same functionality.
Am I missing issues and/or inappropriately minimizing the ones that I've addressed? Are you aware of a post or other source on the underlying principles that I might consult?