【发布时间】:2018-02-19 03:07:51
【问题描述】:
我知道我可以使用类作为哈希键,但这是一个好习惯吗?在性能或测试方面有什么缺点吗?
{
SomeClassA: 'hash value',
AnotherClass: 'hash value'
}
【问题讨论】:
-
只是好奇,你的用例是什么?为什么会有这样的要求?
标签: ruby-on-rails ruby
我知道我可以使用类作为哈希键,但这是一个好习惯吗?在性能或测试方面有什么缺点吗?
{
SomeClassA: 'hash value',
AnotherClass: 'hash value'
}
【问题讨论】:
标签: ruby-on-rails ruby
{
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
【讨论】:
{ 0_foo: 2 }
:0_foo 无效。您必须改用:'0_foo' 或{ '0_foo': 2 }。
虽然你可以做到,但我想不出使用它的理由。使用符号或字符串作为键更有效,因为程序不必加载整个类。 (旁注,正如其他人指出的那样,您的示例实际上是使用符号键,您需要使用哈希火箭来使用类名作为键)
【讨论】:
你所拥有的不是类键而是符号。 试试
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 文档
【讨论】:
该哈希使用符号而不是类作为键,但您可以通过这样做使用Class
hash = { SomeClassA => "some value" }
我想不出为什么它会比使用任何其他对象更糟糕,因为
Ruby 中的类是一等对象——每个都是类
Class的一个实例
所以
{ SomeClassA => "some value" }
在功能上等同于
{ "Some String" => "some value" }
【讨论】: