在 Ruby 中什么时候使用常量而不是实例变量?
When to use constants instead of instance variables in Ruby?
我明白实例变量是状态,常量是常量。有什么理由(除了约定之外)使用常量而不是实例变量吗?使用常量有 memory/speed 优势吗?
与实例变量不同,常量是全局的。如果您尝试重新分配他们的价值,他们至少会抱怨。
虽然 memory/speed 中可能存在理论上的差异,但在实践中是无关紧要的。
这里有几点需要考虑:
- 值会在对象的生命周期内改变吗?
- 您是否需要覆盖子 classes 中的值?
- 是否需要在运行时配置值?
最好的常量是那些只更新软件就不会真正改变的常量:
class ExampleClass
STATES = %i[
off
on
broken
].freeze
end
通常您在 class 内部使用这些常量并避免共享它们。当您共享它们时,它们的使用方式会受到限制。例如,如果另一个 class 引用了 ExampleClass::STATES
,那么您不能在不更改其他代码的情况下更改该结构。
您可以通过提供 接口 使它更抽象:
class ExampleClass
def self.states
STATES
end
end
如果您将来更改该常量的结构,您始终可以保留旧行为:
class ExampleClass
STATES = {
on: 'On',
off: 'Off',
broken: 'Broken'
}.freeze
def self.states
STATES.keys
end
end
当您谈论实例变量时,您指的是您可以配置的东西:
class ConfigurableClass
INITIAL_STATE_DEFAULT = :off
def self.initial_state
@initial_state || INITIAL_STATE_DEFAULT
end
def self.initial_state=(value)
@initial_state = value ? value.to_sym
end
end
常量很棒,因为它们定义一次并在整个过程中使用,因此从技术上讲它们更快。实例变量仍然非常快,并且通常是必要的,如上所示。
您可能没有意识到这一点,但是 类 和模块被认为是常量。
pry(main)> Foo
NameError: uninitialized constant Foo
关于何时应该使用常量,我能给出的最佳建议是当它们确实是常量时。例如,如果我在 rails 中创建范围以查找最近的所有 Foo
,我将创建一个常量来显示最近的内容。
class Foo < ActiveRecord::Base
DAYS_TILL_OLD = 7.days
scope :recent, -> { where "created_at > ?", DateTime.now - DAYS_TILL_OLD }
end
我明白实例变量是状态,常量是常量。有什么理由(除了约定之外)使用常量而不是实例变量吗?使用常量有 memory/speed 优势吗?
与实例变量不同,常量是全局的。如果您尝试重新分配他们的价值,他们至少会抱怨。
虽然 memory/speed 中可能存在理论上的差异,但在实践中是无关紧要的。
这里有几点需要考虑:
- 值会在对象的生命周期内改变吗?
- 您是否需要覆盖子 classes 中的值?
- 是否需要在运行时配置值?
最好的常量是那些只更新软件就不会真正改变的常量:
class ExampleClass
STATES = %i[
off
on
broken
].freeze
end
通常您在 class 内部使用这些常量并避免共享它们。当您共享它们时,它们的使用方式会受到限制。例如,如果另一个 class 引用了 ExampleClass::STATES
,那么您不能在不更改其他代码的情况下更改该结构。
您可以通过提供 接口 使它更抽象:
class ExampleClass
def self.states
STATES
end
end
如果您将来更改该常量的结构,您始终可以保留旧行为:
class ExampleClass
STATES = {
on: 'On',
off: 'Off',
broken: 'Broken'
}.freeze
def self.states
STATES.keys
end
end
当您谈论实例变量时,您指的是您可以配置的东西:
class ConfigurableClass
INITIAL_STATE_DEFAULT = :off
def self.initial_state
@initial_state || INITIAL_STATE_DEFAULT
end
def self.initial_state=(value)
@initial_state = value ? value.to_sym
end
end
常量很棒,因为它们定义一次并在整个过程中使用,因此从技术上讲它们更快。实例变量仍然非常快,并且通常是必要的,如上所示。
您可能没有意识到这一点,但是 类 和模块被认为是常量。
pry(main)> Foo
NameError: uninitialized constant Foo
关于何时应该使用常量,我能给出的最佳建议是当它们确实是常量时。例如,如果我在 rails 中创建范围以查找最近的所有 Foo
,我将创建一个常量来显示最近的内容。
class Foo < ActiveRecord::Base
DAYS_TILL_OLD = 7.days
scope :recent, -> { where "created_at > ?", DateTime.now - DAYS_TILL_OLD }
end