使用类常量作为Ruby哈希键

时间:2017-09-10 22:27:42

标签: ruby-on-rails ruby

我知道我可以使用class作为Hash键,但这是一个好习惯吗?在性能或测试方面有任何缺点吗?

{
  SomeClassA: 'hash value',
  AnotherClass: 'hash value'
}

4 个答案:

答案 0 :(得分:6)

{
  SomeClassA: 'hash value',
  AnotherClass: 'hash value'
}

实际上相当于:

{
  :SomeClassA => 'hash value',
  :AnotherClass => 'hash value'
}

键是符号。在" new"文字哈希语法键只被视为文字,它们被转换为符号(假设它们是有效的语法)。

要使用常量,范围或任何其他类型的对象,您可以将其作为使用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

但我宁愿在那里使用案例陈述,因为它的意图更清晰,更灵活。

  

在性能或测试方面是否有任何缺点?

您创建的每个哈希都会有一些键指向内存中完全相同的对象,就像您使用符号一样。

一个很大的问题是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

答案 1 :(得分:3)

该哈希使用符号而不是类作为键,但您可以通过

使用Class
hash = { SomeClassA => "some value" }

我无法想到为什么它会比使用任何其他对象更糟糕,因为

  

Ruby中的类是第一类对象---每个对象都是类Class

的实例

所以

{ SomeClassA => "some value" }

在功能上等同于

{ "Some String" => "some value" }

答案 2 :(得分:2)

你所拥有的不是课堂钥匙而是符号。 尝试

class A
end

class B
end

hash = {A: "Some", B: "Code"}
hash.keys[0].class
=> Symbol

但仍A.class =&gt; Class

如果是符号效果,POST很棒

您也可以查看有关user-defined class as hash keys

的ruby文档

答案 3 :(得分:0)

虽然你可以做到,但我想不出使用它的原因。使用符号或字符串作为键更有效,因为程序不必加载整个类。 (旁注,正如其他人指出的那样,你的例子实际上是使用符号键,你需要使用哈希火箭来使用类名作为键)