<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">There’s a case where a property (or function) override in a subclass’ extension leads to unexpected behavior:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">class</span> Base: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">NSObject</span> {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> directProperty: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">String</span> { <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"This is Base"</span> }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> indirectProperty: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">String</span> { <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">directProperty</span> }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">class</span> Sub : <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Base</span> { }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(187, 44, 162);" class="">extension<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Sub</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">override</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> directProperty: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">String</span> { <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"This is Sub"</span> }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div><div class=""><br class=""></div><div class="">Accessing “directProperty” works as expected:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">Base<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">().</span>directProperty<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// “This is Base“</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">Sub<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">().</span>directProperty<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// “This is Sub“</span></div></div><div class=""><br class=""></div><div class="">Accessing “indirectProperty”, shows the unexpected behavior:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">Base<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">().</span>indirectProperty<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// “This is Base“</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Sub</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">().</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">indirectProperty</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>// “This is Base“ &lt;- Unexpected!</div></div><div class=""><br class=""></div><div class="">Adding the “dynamic” keyword to Base.directProperty resolves the issue, so it seems like the implementation of “indirectProperty” always accesses “directProperty” of the Base class directly instead of dispatching dynamically.</div><div class=""><br class=""></div><div class="">I think this is a bug, either because this doesn’t work as expected at runtime, or because it compiles at all. Because the Language Guide for Swift 2.1, chapter “Extensions” states in a note near the beginning:</div><div class=""><blockquote type="cite" class="">“Extensions can add new functionality to a type, but they cannot override existing functionality.”</blockquote></div><div class=""><a href="https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html#//apple_ref/doc/uid/TP40014097-CH24-ID151" class="">https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html#//apple_ref/doc/uid/TP40014097-CH24-ID151</a></div><div class=""><br class=""></div><div class="">That sounds to me like the “override” keyword must not appear in an extension. Curiously enough, the above code compiles and some parts of it even run without issues despite violating the Language Guide. If “Base” does not inherit from NSObject but becomes a root class instead, the compiler produces the following error in the extension:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">Declarations in extensions cannot override yet</blockquote></div><div class=""><br class=""></div><div class="">Note the “yet”. Seems like this is just not done yet. Also, I don’t understand how this feature could work except if overriding properties and methods in a subclass’ extension will only be supported if the original property or method was declared as dynamic. Otherwise the compiler could inline their implementation and the extension’s implementation would never be called – assuming the extension isn’t known at compile time, as could be the case for extensions to classes of system frameworks. Everything’s probably fine with Whole Module Optimization if the module contains all the classes and extensions.</div><div class=""><br class=""></div><div class="">Anyways, if this will be supported for non-Objective-C classes in the future, the above bug could point to something that doesn’t work correctly.</div><div class=""><br class=""></div><div class="">Also note that this could be related to (but not the same as) a bug reported already where methods implemented in a protocol extension cannot be overridden by a conforming class’ subclass:</div><div class=""><a href="https://bugs.swift.org/browse/SR-103" class="">https://bugs.swift.org/browse/SR-103</a></div></body></html>