使用类常量作为 Ruby 哈希键
Posted
技术标签:
【中文标题】使用类常量作为 Ruby 哈希键【英文标题】:Use class constant as Ruby hash key 【发布时间】:2018-02-19 03:07:51 【问题描述】:我知道我可以使用类作为哈希键,但这是一个好习惯吗?在性能或测试方面有什么缺点吗?
SomeClassA: 'hash value',
AnotherClass: 'hash value'
【问题讨论】:
只是好奇,你的用例是什么?为什么会有这样的要求? 【参考方案1】:
SomeClassA: 'hash value',
AnotherClass: 'hash value'
实际上相当于:
:SomeClassA => 'hash value',
:AnotherClass => 'hash value'
键是符号。在“新”文字哈希语法中,键只是被视为转换为符号的文字(只要它们是有效的语法)。
要使用常量、范围或任何其他类型的对象,您可以梦想成键,您需要使用 hashrockets:
SomeClassA => 'hash value',
AnotherClass => 'hash value'
这是一个好习惯吗?
这是一种可以在少数有限情况下使用的技术。例如替换一系列if
语句。
def foo(bar)
if bar.is_a? SomeClassA
'hash value'
end
if bar.is_a? AnotherClass
'another value'
end
end
def foo(bar)
SomeClassA => 'hash value',
AnotherClass => 'another value'
[bar]
end
但无论如何,我宁愿在此处使用 case 语句,因为它的意图更清晰,更灵活。
在性能或测试方面有什么缺点吗?
您创建的每个哈希都有指向内存中完全相同对象的键,就像您使用符号时一样。
一个大问题是 Rails 猴子补丁 const_missing
以自动加载文件 - 当您引用类名时,rails 会将文件从文件系统加载到内存中。这就是您声明与以下对象的关联的原因:
class Foo < ApplicationRecord
belongs_to :bar, class_name: "Baz"
end
它让 Rails 在需要时懒加载 Baz。你可以对上面的例子做同样的事情:
def foo(bar)
'SomeClassA' => 'hash value',
'AnotherClass' => 'another value'
[bar.name]
end
【讨论】:
谢谢,这就是我要找的东西,但是 bar.name.to_sym 如何解决这里的自动加载问题?能给我举个例子吗?如果在大多数情况下只通过 foo(SomeClassA) 似乎没问题会发生什么? "...强制您放入密钥中的任何内容.." 可能有点强。 'Yes' 用于字符串、常量以及局部变量和方法的名称(不带前导冒号),但据我所知,'no' 用于其他任何东西(整数、浮点数、符号、实例名称、类和全局变量、数组,哈希值等)。您可能希望更具体。除了那个小问题,很好的答案。 有效点@CarySwoveland。它实际上只是将以任何字母开头的字符串强制转换为符号,因为其他任何内容都会导致语法错误,即使是 0_foo: 2
那是因为:0_foo
无效。您必须改用:'0_foo'
或 '0_foo': 2
。
没错,就是在解析hash的时候进行语法检查。但同样的规则应该适用。 (IIRC,有一个 Ruby 版本无法解析带引号的符号键)【参考方案2】:
虽然你可以做到,但我想不出使用它的理由。使用符号或字符串作为键更有效,因为程序不必加载整个类。 (旁注,正如其他人指出的那样,您的示例实际上是使用符号键,您需要使用哈希火箭来使用类名作为键)
【讨论】:
【参考方案3】:你所拥有的不是类键而是符号。 试试
class A
end
class B
end
hash = A: "Some", B: "Code"
hash.keys[0].class
=> Symbol
但还是A.class
=> Class
在符号性能的情况下,POST 很棒
您还可以查看有关 user-defined class as hash keys 的 ruby 文档
【讨论】:
+1 但在您的答案中声明 A 类和 B 类是无关紧要的,而且对于您为什么这样做,您不觉得吗?【参考方案4】:该哈希使用符号而不是类作为键,但您可以通过这样做使用Class
hash = SomeClassA => "some value"
我想不出为什么它会比使用任何其他对象更糟糕,因为
Ruby 中的类是一等对象——每个都是类
Class
的一个实例
所以
SomeClassA => "some value"
在功能上等同于
"Some String" => "some value"
【讨论】:
以上是关于使用类常量作为 Ruby 哈希键的主要内容,如果未能解决你的问题,请参考以下文章