<div dir="ltr"><div class="gmail_default" style="font-family:georgia,serif">No. I don&#39;t think what you so called principle should be applied here. For example, I have a `class Fruit`, then I have a `class Apple:Fruit`. If they are using different `hashValue` generating method, you suggest me to use composition instead of inheritance?</div><div class="gmail_default" style="font-family:georgia,serif"><br></div><div class="gmail_default" style="font-family:georgia,serif">Also, it is very common for subclass to override super class `hashValue`. Supposing opposite, if we also have another class called `class Banana:Fruit`, we may get the result that an `Apple` is equals to a `Banana`, using `Fruit`,  just because they have the same `hashValue`.</div><div class="gmail_default" style="font-family:georgia,serif"><br></div><div class="gmail_default" style="font-family:georgia,serif">If we stick to the super class `hashValue`, we may also not get the differences between instances of a certain subclass. For example, we may get the result that a `redApple` equals to a `greenApple`.</div><div class="gmail_default" style="font-family:georgia,serif"><br></div><div class="gmail_default" style="font-family:georgia,serif">So in my option, if one instance equals to another instance, the foundation should be that the `type(of:instance)` equals. If you want to enlarge the type to their super class, you need to be careful, as they are not guaranteed automatically.</div><div class="gmail_default" style="font-family:georgia,serif"><br></div><div class="gmail_default" style="font-family:georgia,serif">Zhaoxin</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 2, 2016 at 7:32 AM, Jordan Rose <span dir="ltr">&lt;<a href="mailto:jordan_rose@apple.com" target="_blank">jordan_rose@apple.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>The <a href="https://en.wikipedia.org/wiki/Liskov_substitution_principle" target="_blank">Liskov substitution principle</a> says that a B should always be able to be treated like an A. Your Set&lt;A&gt; may <i>already</i> contain Bs, even without them ever being statically typed as B. If you think A and B are unrelated types, you should be using composition rather than inheritance.</div><div><br></div><div>If a subclass overrides hashValue, they must be in a position to affect == as well, and it must work no matter which object is on the left-hand side. NSObject does this by having == call the isEqual(_:) method, but you still need to design your class hierarchy and isEqual(_:) methods carefully.</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>Jordan</div></font></span><div><div class="h5"><div><br></div><br><div><blockquote type="cite"><div>On Sep 1, 2016, at 16:28, Zhao Xin &lt;<a href="mailto:owenzx@gmail.com" target="_blank">owenzx@gmail.com</a>&gt; wrote:</div><br><div><div dir="ltr"><div class="gmail_default" style="font-family:georgia,serif">I believe if B inherits A, they are not the same type. So the rule doesn&#39;t apply here.</div><div class="gmail_default" style="font-family:georgia,serif"><br></div><div class="gmail_default" style="font-family:georgia,serif">Zhaoxin</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 2, 2016 at 7:02 AM, Nick Brook <span dir="ltr">&lt;<a href="mailto:nrbrook@gmail.com" target="_blank">nrbrook@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Hi Jordan,<div><br></div><div>Thanks for the advice.</div><div><br></div><div>What if a subclass does implement hashValue differently? It seems you are saying a subclass should never override hashValue? Should Set not compare elements with == instead of hashValue?<br><div><br></div><div>
Thanks<br><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">Nick</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">M: <a href="tel:%2B44%20%280%297986%20048%20141" value="+447986048141" target="_blank">+44 (0)7986 048 141</a></span><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">W: <a href="http://nickbrook.me/" target="_blank">http://nickbrook.me</a></div>
</div><div><div>
<br><div><blockquote type="cite"><div>On 1 Sep 2016, at 23:55, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" target="_blank">jordan_rose@apple.com</a>&gt; wrote:</div><br><div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite"><div><br>On Sep 1, 2016, at 15:44, Zhao Xin via swift-users &lt;<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>&gt; wrote:</div><br><div><div dir="ltr"><div class="gmail_default" style="font-family:georgia,serif">Hi Nick,</div><div class="gmail_default" style="font-family:georgia,serif"><br></div><div class="gmail_default" style="font-family:georgia,serif">Glad to help.</div><div class="gmail_default" style="font-family:georgia,serif"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">but when using third party classes I don’t know if the hash values are comparable<br></blockquote><div><br></div><div class="gmail_default" style="font-family:georgia,serif">You can create an extension with a convenient init(:), which creates a new instance of  the super class basing on the instance of the sub class. That will guarantee the subtraction. Below code works in Xcode 7.3.1 with Swift 2.2.<br></div><div class="gmail_default" style="font-family:georgia,serif"><br></div><div class="gmail_default"><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span style="color:rgb(187,44,162)">import</span><span><span> </span>Foundation</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px"><span></span><br></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span style="color:rgb(187,44,162)">func</span><span><span> </span>==(lhs:<span> </span></span><span style="color:rgb(79,129,135)">Foo</span><span>, rhs:<span> </span></span><span style="color:rgb(79,129,135)">Foo</span><span>) -&gt;<span> </span></span><span style="color:rgb(112,61,170)">Bool</span><span><span> </span>{</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>   <span> </span></span><span style="color:rgb(187,44,162)">return</span><span><span> </span>lhs.</span><span style="color:rgb(79,129,135)">id</span><span><span> </span>== rhs.</span><span style="color:rgb(79,129,135)">id</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>}</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px"><span></span><br></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(112,61,170)"><span style="color:rgb(187,44,162)">class</span><span><span> </span>Foo:</span><span>Hashable</span><span><span> </span>{</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>   <span> </span></span><span style="color:rgb(187,44,162)">let</span><span><span> </span>id:</span><span style="color:rgb(112,61,170)">Int</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>   <span> </span></span><span style="color:rgb(187,44,162)">var</span><span><span> </span>hashValue:<span> </span></span><span style="color:rgb(112,61,170)">Int</span><span><span> </span>{</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>       <span> </span></span><span style="color:rgb(187,44,162)">return</span><span><span> </span></span><span style="color:rgb(79,129,135)">id</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>    }</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px"><span>    </span><br></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>   <span> </span></span><span style="color:rgb(187,44,162)">required</span><span><span> </span></span><span style="color:rgb(187,44,162)">init</span><span>(</span><span style="color:rgb(187,44,162)">_</span><span><span> </span>id:</span><span style="color:rgb(112,61,170)">Int</span><span>) {</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>       <span> </span></span><span style="color:rgb(187,44,162)">self</span><span>.</span><span style="color:rgb(79,129,135)">id</span><span><span> </span>= id</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>    }</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>}</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px"><span></span><br></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span style="color:rgb(187,44,162)">class</span><span><span> </span>Bar:</span><span style="color:rgb(79,129,135)">Foo</span><span><span> </span>{</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>   <span> </span></span><span style="color:rgb(187,44,162)">override</span><span><span> </span></span><span style="color:rgb(187,44,162)">var</span><span><span> </span>hashValue:<span> </span></span><span style="color:rgb(112,61,170)">Int</span><span><span> </span><wbr>{</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>       <span> </span></span><span style="color:rgb(187,44,162)">return</span><span><span> </span></span><span style="color:rgb(79,129,135)">id</span><span><span> </span>*<span> </span></span><span style="color:rgb(39,42,216)">5</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>    }</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span>}</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px"><span></span><br></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span style="color:rgb(187,44,162)">var</span><span><span> </span>fooSet:</span><span style="color:rgb(112,61,170)">Set</span><span>&lt;</span><span style="color:rgb(79,129,135)">Foo</span><span>&gt; = [</span><span style="color:rgb(79,129,135)">Foo</span><span>(</span><span style="color:rgb(39,42,216)">10</span><span>),<span> </span></span><span style="color:rgb(79,129,135)">Foo</span><span>(</span><span style="color:rgb(39,42,216)">9</span><span>),<span> </span></span><span style="color:rgb(79,129,135)">Foo</span><span>(</span><span style="color:rgb(39,42,216)">8</span><span>),<span> </span></span><span style="color:rgb(79,129,135)">Foo</span><span>(</span><span style="color:rgb(39,42,216)"><wbr>7</span><span>)]</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span style="color:rgb(187,44,162)">var</span><span><span> </span>barSet:</span><span style="color:rgb(112,61,170)">Set</span><span>&lt;</span><span style="color:rgb(79,129,135)">Bar</span><span>&gt; = [</span><span style="color:rgb(79,129,135)">Bar</span><span>(</span><span style="color:rgb(39,42,216)">8</span><span>),<span> </span></span><span style="color:rgb(79,129,135)">Bar</span><span>(</span><span style="color:rgb(39,42,216)">7</span><span>),<span> </span></span><span style="color:rgb(79,129,135)">Bar</span><span>(</span><span style="color:rgb(39,42,216)">6</span><span>),<span> </span></span><span style="color:rgb(79,129,135)">Bar</span><span>(</span><span style="color:rgb(39,42,216)">5</span><span><wbr>)]</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px"><span></span><br></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(0,132,0)"><span>//fooSet.subtract(barSet) // error: cannot invoke &#39;subtract&#39; with an argument list of type &#39;(Set&lt;Bar&gt;)&#39;</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(79,129,135)"><span>fooSet</span><span><span> </span>=<span> </span></span><span>fooSet</span><span>.</span><span style="color:rgb(61,29,129)">subtract</span><span>(</span><span>barSe<wbr>t</span><span><span> </span></span><span style="color:rgb(187,44,162)">as</span><span><span> </span></span><span style="color:rgb(112,61,170)">Set</span><span>&lt;</span><span>Foo</span><span>&gt;) </span><span style="color:rgb(0,132,0);font-family:menlo">// works, but not what we want</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal"><span style="color:rgb(79,129,135)">fooSet</span><span>.</span><span style="color:rgb(61,29,129)">forEach</span><span><span> </span>{<span> </span></span><span style="color:rgb(61,29,129)">print</span><span>(</span><span style="color:rgb(209,47,27)">&quot;</span><span>\</span><span style="color:rgb(209,47,27)">(</span><span>$0.</span><span style="color:rgb(187,44,162)">d<wbr>ynamicType</span><span style="color:rgb(209,47,27)">), id:</span><span>\</span><span style="color:rgb(209,47,27)">(</span><span>$0.</span><span style="color:rgb(79,129,135)">id</span><span style="color:rgb(209,47,27)">)&quot;</span><span>) }</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(0,132,0)"><span>/*</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(0,132,0)"><span> Foo, id:7</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(0,132,0)"><span> Foo, id:10</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(0,132,0)"><span> Foo, id:9</span></div><div style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(0,132,0)"><span>*/</span></div></div></div></div></blockquote><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">This isn&#39;t really a sensible thing to do. The rules for Hashable require that `a == b` implies `a.hashValue == b.hashValue`, and `a.hashValue != b.hashValue` implies `a != b`. If you break these rules you&#39;re going to have problems no matter what static types you&#39;re using.</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Upcasting from Set&lt;Bar&gt; to Set&lt;Foo&gt; is the most concise way to solve this problem.</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Jordan</div></div></blockquote></div><br></div></div></div></div></blockquote></div><br></div>
</div></blockquote></div><br></div></div></div></blockquote></div><br></div>