[swift-users] Subtract a set of a subclass?

Nick Brook nrbrook at gmail.com
Thu Sep 1 18:02:06 CDT 2016


Hi Jordan,

Thanks for the advice.

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?

Thanks
Nick

M: +44 (0)7986 048 141
W: http://nickbrook.me <http://nickbrook.me/>
> On 1 Sep 2016, at 23:55, Jordan Rose <jordan_rose at apple.com> wrote:
> 
>> 
>> On Sep 1, 2016, at 15:44, Zhao Xin via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>> 
>> Hi Nick,
>> 
>> Glad to help.
>> 
>> but when using third party classes I don’t know if the hash values are comparable
>> 
>> 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.
>> 
>> import Foundation
>> 
>> func ==(lhs: Foo, rhs: Foo) -> Bool {
>>     return lhs.id == rhs.id
>> }
>> 
>> class Foo:Hashable {
>>     let id:Int
>>     var hashValue: Int {
>>         return id
>>     }
>>     
>>     required init(_ id:Int) {
>>         self.id = id
>>     }
>> }
>> 
>> class Bar:Foo {
>>     override var hashValue: Int {
>>         return id * 5
>>     }
>> }
>> 
>> var fooSet:Set<Foo> = [Foo(10), Foo(9), Foo(8), Foo(7)]
>> var barSet:Set<Bar> = [Bar(8), Bar(7), Bar(6), Bar(5)]
>> 
>> //fooSet.subtract(barSet) // error: cannot invoke 'subtract' with an argument list of type '(Set<Bar>)'
>> fooSet = fooSet.subtract(barSet as Set<Foo>) // works, but not what we want
>> fooSet.forEach { print("\($0.dynamicType), id:\($0.id)") }
>> /*
>>  Foo, id:7
>>  Foo, id:10
>>  Foo, id:9
>> */
> 
> This isn'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're going to have problems no matter what static types you're using.
> 
> Upcasting from Set<Bar> to Set<Foo> is the most concise way to solve this problem.
> 
> Jordan

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160902/433772bf/attachment.html>


More information about the swift-users mailing list