<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto">Unfortunately the error messages you get with protocols are limited :). The compiler is doing the right thing, no bug. The problem is that it is really easy to mak<br><br><div id="AppleMailSignature">-- Howard. </div><div><br>On 1 Jan 2018, at 3:40 pm, Toni Suter via swift-users <<a href="mailto:swift-users@swift.org">swift-users@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html; charset=utf-8">Hi Marc,<div class=""><br class=""></div><div class="">There are several subtleties here, but I think the compiler is actually doing the right thing.</div><div class=""><br class=""></div><div class=""><div class="">The second class defines a static property that looks like it is 'overriding' the static property from</div></div><div class="">the protocol extension, but since the types don't match (String vs. String?), it sort of 'overloads'</div><div class="">the property (similar to function overloading). Nevertheless, the class still fulfills the requirements</div><div class="">of the Trackable protocol, by inheriting the static property from the protocol extension.</div><div class=""><br class=""></div><div class="">When you access analyticsID like a regular static property, the Swift compiler will choose the String property,</div><div class="">because it shadows the String? property:</div><div class=""><br class=""></div><div class=""><font face="Courier New" class="">let x = Something2.analyticsID</font></div><div class=""><font face="Courier New" class="">print(x)<span class="Apple-tab-span" style="white-space: pre;">                                        </span>// Wrong but compilers, returns wrong value</font></div><div class=""><font face="Courier New" class="">print(type(of: x))<span class="Apple-tab-span" style="white-space: pre;">                                </span>// String</font></div><div class=""><br class=""></div><div class="">However, when the context of the expression Something2.analyticsID expects a String?, the Swift compiler will</div><div class="">choose the String? property:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><font face="Courier New" class="">let a: String? = Something2.analyticsID<span class="Apple-tab-span" style="white-space: pre;">                </span>// explicit type annotation demands a String?</font></div><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><font face="Courier New" class="">print(a)<span class="Apple-tab-span" style="white-space: pre;">                                        </span>// nil</font></div><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><font face="Courier New" class="">print(type(of: a))<span class="Apple-tab-span" style="white-space: pre;">                                </span>// Optional<String></font></div><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><font face="Courier New" class=""><br class=""></font></div><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><font face="Courier New" class="">let b = Something2.analyticsID as String?<span class="Apple-tab-span" style="white-space: pre;">        </span>// type cast demands a String?</font></div><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><font face="Courier New" class="">print(b)<span class="Apple-tab-span" style="white-space: pre;">                                        </span>// nil</font></div><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><font face="Courier New" class="">print(type(of: b))<span class="Apple-tab-span" style="white-space: pre;">                                </span>// Optional<String></font></div></div><div class=""><br class=""></div><div class="">A similar thing happens, when you write Something2.analyticsID ?? "nil". The nil coalescing operator ?? demands that the first parameter</div><div class="">is an optional. Therefore, the Swift compiler will choose the String? property instead of the String property.</div><div class=""><br class=""></div><div class="">I hope this helps!</div><div class=""><br class=""></div><div class="">Best regards,</div><div class="">Toni</div><div style=""><br class=""><blockquote type="cite" class=""><div class="">Am 01.01.2018 um 18:29 schrieb Marc Palmer via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>>:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi,<br class=""><br class="">I hope everybody had a great New Year celebration.<br class=""><br class="">I was tracking down a weird bug in my Swift code today. A property defined in a class in order to conform to a protocol was not being seen. A protocol extension provided a default value of `nil` for this property, so I knew where it was coming from. Turned out, in my class I had defined the property with the correct name but incorrect type - I declared it as `String` instead of `String?`. <br class=""><br class="">I isolated this behaviour in a playground, shown below, and it is pretty weird behaviour.<br class=""><br class="">The output is:<br class=""><br class="">Something1 has id: nil<br class="">Something2 has id: nil<br class="">Something3 has id: Correct<br class="">-- Direct access--<br class="">Something1 - nil<br class="">Something2 - nil<br class="">Something2 with String(describing:) - Wrong but compiles, returns wrong value<br class="">Something3 - Correct<br class=""><br class="">The playground code:<br class=""><br class="">======================<br class=""><br class="">protocol Trackable {<br class=""> static var analyticsID: String? { get }<br class="">}<br class=""><br class="">extension Trackable {<br class=""> static var analyticsID: String? { return nil }<br class="">}<br class=""><br class="">class Something1: Trackable {<br class="">}<br class=""><br class="">class Something2: Trackable {<br class=""> static var analyticsID: String = "Wrong but compiles, returns wrong value"<br class="">}<br class=""><br class="">class Something3: Trackable {<br class=""> static var analyticsID: String? = "Correct"<br class="">}<br class=""><br class="">func getID<T: Trackable>(_ trackable: T.Type) {<br class=""> if let id = trackable.analyticsID {<br class=""> print("\(trackable) has id: \(id)")<br class=""> } else {<br class=""> print("\(trackable) has id: nil")<br class=""> }<br class="">}<br class=""><br class="">getID(Something1.self)<br class="">getID(Something2.self)<br class="">getID(Something3.self)<br class=""><br class="">print("-- Direct access--")<br class="">print("Something1 - \(Something1.self.analyticsID ?? "nil")")<br class="">print("Something2 A - \(Something2.self.analyticsID ?? "nil")")<br class="">print("Something2 with String(describing:) - \(String(describing: Something2.self.analyticsID))")<br class="">print("Something3 - \(Something3.self.analyticsID ?? "nil")”)<br class="">======================<br class=""><br class="">Thanks in advance for any information about my misinterpretations or recommendations of what parts are actually undesirable so that I can raise the JIRAs.<br class=""><br class="">Cheers<br class=""><br class="">—<br class="">Marc Palmer<br class="">Montana Floss Co. Ltd.<br class=""><br class="">Soundproof – Music Player for Practice <br class=""><a href="http://getsoundproof.com" class="">http://getsoundproof.com</a><br class=""><br class=""><br class=""><br class="">_______________________________________________<br class="">swift-users mailing list<br class=""><a href="mailto:swift-users@swift.org">swift-users@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-users">https://lists.swift.org/mailman/listinfo/swift-users</a><br class=""></div></div></blockquote></div><br class=""></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-users mailing list</span><br><span><a href="mailto:swift-users@swift.org">swift-users@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-users">https://lists.swift.org/mailman/listinfo/swift-users</a></span><br></div></blockquote></body></html>