Swift 3 中的 Any 、 Hashable 、 AnyHashable 有什么区别?
我通过大量教程摸索以了解上述 3 个术语之间的区别并找到新术语 type erased
容器,现在这让我感到困惑.这引发了很多问题.
I scratch my head through lots of tutorials to understand the difference between the above 3 terms and find new term type erased
container, now it becomes confusing to me. It raises lots of question.
为什么 Swift 引入了 AnyHashable
?
Why does Swift introduce AnyHashable
?
这三个术语之间的根本区别是什么?
What is the fundamental difference between these 3 terms?
Any
和 AnyHashable
的区别?
Hashable
和 AnyHashable
的区别?
何时使用 Hashable
以及何时使用 AnyHashable
?
When to use Hashable
and when to use AnyHashable
?
最后但最令人困惑的是,AnyHashable
上下文中type erased
术语的含义是什么?
Last but most confusing, what is the meaning of type erased
term in the context of AnyHashable
?
作为上下文,我遵循了 Swift Evolution ProposalSE-0131.
As a context, I followed Swift Evolution Proposal SE-0131.
理解它们是什么比它们之间有什么区别更重要.
It's more important to understand what they are than what are the differences between them.
Any
表示任何东西",包括 swift 枚举、元组、闭包、结构、类、协议等等.每种类型都可以分配给 Any
类型的变量.
Any
means "anything", ranging from swift enums, tuples, closures, structs, classes, protocols, whatever. Every type can be assigned to a variable of type Any
.
Hashable
是一个协议,它说这个对象可以被散列,即有一个散列码".如果您的对象可以散列,请实现此协议,因为很多数据结构(即字典和集合)都需要它.
Hashable
is protocol that says "this object can be hashed i.e. has a hashcode". If your object can be hashed, implement this protocol, because lots of data structures (namely dictionaries and sets) need it.
那么什么是AnyHashable
?
通常,如果您尝试这样做:
Normally, if you try to do this:
let a: Set<Hashable>?
它不会编译.这是因为 Hashable
继承自包含 Self
的 Equatable
.
it does not compile. This is because Hashable
inherits from Equatable
which contains Self
.
现在,假设您想将一个方法从 Objective-C 移植到 swift.该方法采用 NSSet
类型的参数.在 Swift 中,这会变成一个 Set
,但它的泛型参数是什么?如果我们像处理 NSArray
那样只放置 Any
,它是行不通的,因为 Set
的对象必须是可散列的.但是如果我们放置 Set
它也不起作用,因为 Hashable
只能用作通用约束.这就是为什么他们用 AnyHashable
包裹了 Hashable
,不 使用 Self
,因此可以用作通用参数.
Now, let's say you want to port a method from Objective-C to swift. That method takes a parameter of type NSSet
. In Swift, this will turn into a Set
, but what is its generic parameter? If we just put Any
like we do with NSArray
s, it does not work because Set
's objects must be hashable. But if we put Set<Hashable>
it does not work either because Hashable
can only be used as a generic constraint. That's why they wrapped Hashable
with an AnyHashable
that does not use Self
and so can be used as a generic parameter.
关于类型擦除"的含义:
Regarding what "type erased" means:
在协议中包含 Self
有点像 就像一个带有泛型参数的协议,泛型参数总是符合的类.这导致协议不能像 Set
那样单独使用,因为通用参数"是未知的.AnyHashable
完全不使用 Self
解决了这个问题,所以它现在变成了一个普通的结构体.它擦除"了通用的 Self
类型.
Having Self
in a protocol is kind of like a protocol with a generic parameter, and the generic parameter is always the conforming class. This causes the protocols to be unable to be used on its own like Set<Hashable>
because the "generic parameter" is unknown. AnyHashable
solves this problem by not using Self
at all so it now becomes a normal struct. It "erases" the generic Self
type.