I'd like to use my own class to process it using a set.
For that reason, I would like to conform to the Hashable protocol to my own model.
From the translated version of the swift reference,
structure GridPoint{
varx —Int
variable —Int
}
extension GridPoint: Hashable {
var hashValue: Int {
return x.hashValue^y.hashValue
}
static func==(lhs:GridPoint, rhs:GridPoint) - >Bool{
return lhs.x==rhs.x&lhs.y==rhs.y
}
}
This part is difficult to understand, so I asked you a question.
So what do we have to define?
swift swift5
"
(Thanks to Nagonsoftware)
The Hashable
chimo (which is a common concept in other languages with similar mechanisms) is
hashValue
to check if it can be equal
hashValue
must be equal to never ==
hashValue
is equal, use ==
to see if it is actually equal
Use hashValue
to check if it can be equal.
hashValue
must be equal to never ==
If hashValue
is equal, use ==
to check if it is actually equal
That's how you use it.
For the current Swift, Hashable
is defined as follows:
public protocol Hashable:Equatable{
var hashValue: Int {get}
funchash (into hasher:inout hasher)
}
Also, Equatable
is defined as follows:
publicprotocolEquatable{
static func==(lhs:Self, rhs:Self)->Bool
}
(The header document contained in Swift's own source contains very useful content, but it was omitted this time because it was all in English.)
In short, you can conform to the Hashable
protocol by defining one method, one property, and one operator.
Properties to get hash values
Method for calculating hash values sequentially
Operator that determines equality==
Properties to retrieve hash values hashValue
Method for calculating hash values sequentially hash(into:)
Operator ==
Because Swift now has a default implementation for hashValue
, you can only prepare hash(into:)
and ==
to match your defined structure
or class
to Hashable
.
(If you really want to do it yourself) Like this:
structure GridPoint{
varx —Int
variable —Int
}
extension GridPoint: Hashable {
public funchash(into hash:inout Hasha) {
x.hash (into: & hasher)
y.hash (into: & hasher)
}
static func==(lhs:GridPoint, rhs:GridPoint) - >Bool{
return lhs.x==rhs.x&lhs.y==rhs.y
}
}
(Note: Implementing the hashValue
directly instead of hash(into:)
is a fairly old fashioned approach.It would be better to look for more new sources.)
One important point here is that hashValue
and ==
must meet the following axioms in order to be consistent.
a==b
will definitely pass a.hashValue==b.hashValue
It may be difficult to immediately understand that the stereotypical implementation described above satisfies this axiom, but it will work.(I'm not confident that I can write long but easy to understand, so I'll break it roughly.)
However, in Swift (4.2 and later), it is rare for structure
and enum
to write such a routine action yourself.
Do not use extension
at all, but write the following definition somewhere:
structure GridPoint:Hashable{
varx —Int
variable —Int
}
The Swift compiler will accept GridPoint
as the Hashable
type to issue any errors or warnings.Of course, it can also be used as a Key
for Set
and Dictionary
.
Suggestion SE-0185 Synthesizing Equatable and Hashable conformance (and subsequent fixes SE-0206 Hashable EnhaSince ncements) was adopted, the Swift compiler automatically creates definitions of hashValue
, hash(into:)
and ==
for the declared data type.Don't worry too much and keep using it.
So if you want to "make your own model conform to the Hashable protocol",
Add:Hashable
to the That's what it means.
If you would like to know the background a little more deeply, or if the data type you define doesn't work, please let us know by commenting.If you want to use a set to process it, you should be able to see that it can be used for Set
right away.
The hash(into:)
method and the ==
operator must be implemented to be consistent, as described above.I don't know what your class
is defined, so I have to show it in general cases, for example,
==
if the values of the properties that will be the two keys are equal.class MyClass {
varkeyValue1: Int
varkeyValue2—String
variableValue1: Double=0.0
variable otherValue2: String = [ ]
init(keyValue1:Int, keyValue2:String) {
self.keyValue1 = keyValue1
self.keyValue2 = keyValue2
}
}
extension MyClass: Hashable {
Define //`==` to match the meaning of what your class represents
static func==(lhs:MyClass, rhs:MyClass) - >Bool{
// If `keyValue1` and `keyValue2` are equal, the two `MyClass` are `==`.
return lhs.keyValue1 == rhs.keyValue1 & lhs.keyValue2 == rhs.keyValue2
}
public funchash(into hash:inout Hasha) {
// Call `hash(into:)` to the property used in `==` to determine whether it is equal or not
keyValue1.hash (into: & hasher)
keyValue2.hash (into: & hasher)
}
}
Implement ==
as described above, and implement hash(into:)
accordingly.
==
if you are referring to the same instance// MyClass definition must be the same as above
extension MyClass: Hashable {
static func==(lhs:MyClass, rhs:MyClass) - >Bool{
// To define `==` if referring to the same instance
return lhs === rhs
}
public funchash(into hash:inout Hasha) {
// Since the address itself is used to determine whether it is equal or not, I will call `hash(into:)` for `ObjectIdentifier(self)`
ObjectIdentifier(self).hash(into:&hasher)
}
}
NSObject
defaults to Hashable
, but the default implementation of hashValue
and ==
differs from the net Swift class as follows:
hashValue
is to invoke NSObjectProtocol.hash
==
is to invoke NSObjectProtocol.isEqual(_:)
Therefore, if you customize the behavior, you must override the hash
property instead of the hash(into:)
operator and the isEqual(_:)
method instead of the ==
operator.
class MyNSClass: The descendant class of the NSObject {//<-`NSObject` is always treated as `Hashable`
varkeyValue1: Int
varkeyValue2—String
variableValue1: Double=0.0
variable otherValue2: String = [ ]
init(keyValue1:Int, keyValue2:String) {
self.keyValue1 = keyValue1
self.keyValue2 = keyValue2
}
// Override `isEqual(_:)` if you want to change the behavior of `==`
override funcisEqual(_object:Any?) - >Bool{
if let rhs = object as ?MyNSClass {
return self.keyValue1 == rhs.keyValue1 & self.keyValue2 == rhs.keyValue2
} else{
return false
}
}
// Make `hash` property consistent with `isEqual(_:)`
override var hash:Int {
var hasher=Hasher()
keyValue1.hash (into: & hasher)
keyValue2.hash (into: & hasher)
return hasher.finalize()
}
}
I don't understand the contents of your self-made class, so I could only write general things, so it might be a little difficult to see.If you have any questions about "self-made classes", you can get a better answer faster if you provide a definition of that class.
617 Uncaught (inpromise) Error on Electron: An object could not be cloned
572 rails db:create error: Could not find mysql2-0.5.4 in any of the sources
911 When building Fast API+Uvicorn environment with PyInstaller, console=False results in an error
574 Who developed the "avformat-59.dll" that comes with FFmpeg?
© 2024 OneMinuteCode. All rights reserved.