哈希¶
一个 Hash 是一个通用的键值对集合,将类型为 K 的键映射到类型为 V 的值。
哈希通常使用哈希字面量创建,哈希字面量由花括号 ({ }) 括起来,其中包含使用 => 作为键和值之间分隔符且用逗号 , 分隔的键值对列表。
{"one" => 1, "two" => 2}
泛型类型参数¶
键 K 和值 V 的泛型类型参数分别从字面量中键或值的类型推断得出。当所有类型都相同时,K/V 等于该类型。否则,它将分别为所有键类型或值类型的并集。
{1 => 2, 3 => 4} # Hash(Int32, Int32)
{1 => 2, 'a' => 3} # Hash(Int32 | Char, Int32)
可以通过在右括号后紧跟 of(用空格分隔)、键类型 (K) 后跟 => 作为分隔符以及值类型 (V) 来指定显式类型。这会覆盖推断出的类型,例如,可以用来创建一个最初只包含某些类型的哈希,但也可以接受其他类型的哈希。
空哈希字面量始终需要类型规范
{} of Int32 => Int32 # => Hash(Int32, Int32).new
类哈希类型字面量¶
Crystal 支持哈希和类哈希类型的附加字面量。它由类型的名称后跟花括号 ({}) 括起来的逗号分隔的键值对列表组成。
Hash{"one" => 1, "two" => 2}
只要类型具有无参数构造函数并响应 []=,就可以使用此字面量。
HTTP::Headers{"foo" => "bar"}
对于像 HTTP::Headers 这样的非泛型类型,这等效于
headers = HTTP::Headers.new
headers["foo"] = "bar"
对于泛型类型,泛型类型会像哈希字面量一样从键和值的类型推断得出。
MyHash{"foo" => 1, "bar" => "baz"}
如果 MyHash 是泛型,上面的代码等效于
my_hash = MyHash(typeof("foo", "bar"), typeof(1, "baz")).new
my_hash["foo"] = 1
my_hash["bar"] = "baz"
类型参数可以作为类型名称的一部分显式指定
MyHash(String, String | Int32){"foo" => "bar"}