在Ruby中何时使用常量而不是实例变量?
我理解实例变量意味着状态,常量意味着常量。除了约定之外,还有什么理由使用常量而不是实例变量吗?使用常量是否有内存/速度优势?常量与实例变量不同,是全局的。如果你试图重新分配他们的价值,他们至少会抱怨在Ruby中何时使用常量而不是实例变量?,ruby,variables,instance,constants,Ruby,Variables,Instance,Constants,我理解实例变量意味着状态,常量意味着常量。除了约定之外,还有什么理由使用常量而不是实例变量吗?使用常量是否有内存/速度优势?常量与实例变量不同,是全局的。如果你试图重新分配他们的价值,他们至少会抱怨 虽然内存/速度在理论上可能存在差异,但在实践中却无关紧要。与实例变量不同,常量是全局变量。如果你试图重新分配他们的价值,他们至少会抱怨 虽然记忆/速度可能存在理论上的差异,但在实践中却无关紧要。 这里有一些要考虑的事情: 该值在对象的生命周期内会发生变化吗? 是否需要重写子类中的值? 您需要在运行时
虽然内存/速度在理论上可能存在差异,但在实践中却无关紧要。与实例变量不同,常量是全局变量。如果你试图重新分配他们的价值,他们至少会抱怨
<>虽然记忆/速度可能存在理论上的差异,但在实践中却无关紧要。
这里有一些要考虑的事情:
该值在对象的生命周期内会发生变化吗? 是否需要重写子类中的值? 您需要在运行时配置该值吗? 最好的常数类型是那些在更新软件之前不会真正改变的常数:class ExampleClass
STATES = %i[
off
on
broken
].freeze
end
通常在类内部使用这些常量,并避免共享它们。当你分享它们时,你对它们的使用受到限制。例如,如果另一个类引用了ExampleClass::STATES,那么您不能在不更改其他代码的情况下更改该结构
您可以通过提供一个接口使其更加抽象:
如果将来更改该常数的结构,则始终可以保留旧的行为:
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
常量非常好,因为它们只定义一次,并在整个过程中使用,所以从技术上讲,它们更快。实例变量仍然很快,并且通常是必要的,如上面所示。
这里有一些要考虑的事情:
该值在对象的生命周期内会发生变化吗? 是否需要重写子类中的值? 您需要在运行时配置该值吗? 最好的常数类型是那些在更新软件之前不会真正改变的常数:class ExampleClass
STATES = %i[
off
on
broken
].freeze
end
通常在类内部使用这些常量,并避免共享它们。当你分享它们时,你对它们的使用受到限制。例如,如果另一个类引用了ExampleClass::STATES,那么您不能在不更改其他代码的情况下更改该结构
您可以通过提供一个接口使其更加抽象:
如果将来更改该常数的结构,则始终可以保留旧的行为:
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
您可能没有意识到这一点,但类和模块被视为常量
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
当然,常数就是常数。这是一个同义反复。这样写是没有意义的,因为你可以在Ruby中改变一个常数,这不是重言式,我明白了。您以两种不同的方式使用常量。当然,常量就是常量。这是一个同义反复。这样写是没有意义的,因为你可以在Ruby中改变一个常数,这不是重言式,我明白了。您以两种不同的方式使用常量。不一定。包含类的模块不一定是常量。Class.new,a=Class.new,@a=Class.new,@@a=Class.new,$a=Class.new。类的实例被分配给常量,但类本身不是常量。@sawa类仍然是常量。当然可以将其分配给变量,但该类仍然是常量。在第一种形式中,返回从调用点可访问的所有常量的名称数组。此列表包括全局范围中定义的所有模块和类的名称。只需亲自查看Object.constants即可。类只是类的实例。您可以拥有未指定给常量的类。foo=Class.new完全有效;然后,您可以使用foo.new实例化它,而不需要使用常量。类被分配给类常量,是的。这并不意味着所有的类都是常量,不一定。包含类的模块不一定是常量
新界南部。Class.new,a=Class.new,@a=Class.new,@@a=Class.new,$a=Class.new。类的实例被分配给常量,但类本身不是常量。@sawa类仍然是常量。当然可以将其分配给变量,但该类仍然是常量。在第一种形式中,返回从调用点可访问的所有常量的名称数组。此列表包括全局范围中定义的所有模块和类的名称。只需亲自查看Object.constants即可。类只是类的实例。您可以拥有未指定给常量的类。foo=Class.new完全有效;然后,您可以使用foo.new实例化它,而不需要使用常量。类被分配给类常量,是的。这并不意味着所有的类都是常量。常量只有在全局上下文中声明时才是全局的,否则它们的作用域与往常一样。作用域常量仍然是全局变量,因为它们只存在于运行时一次,并且可以从任何地方访问。另一方面,实例变量存在于每个对象中,并且只能通过它们所属的对象访问。常量只有在全局上下文中声明时才是全局的,否则它们的作用域与往常一样。作用域常量仍然是全局变量,因为它们只存在于运行时一次,并且可以从任何地方访问。另一方面,实例变量存在于每个对象中,并且只能通过它们所属的对象访问;A.const_get'K'=>cat.True,但是如果你试图重新定义一个常量,那么你会得到各种各样的警告,因此需要做额外的工作来取消定义,然后重新定义它,而不是仅仅分配一个变量。我不确定在Ruby中常量是否真的更快,因为它们在技术上仍然是变量——你可以在运行时读写它们。在编译语言中,编译器可以内联常量以加快速度,但在Ruby中,这将更加困难。@averell对任何类型的方法调用都会产生一个小的惩罚,但随着Ruby版本的发布,这种惩罚会减少。例如,由于内部优化,attr_reader生成的方法比手工编码的等效方法更快。在大多数情况下,这种惩罚是不相关的,但值得了解。@tadman-我以为我们讨论的是访问实例变量和访问常量,所以在这两种情况下都不涉及方法调用。不过,我同意常数可能有一些优化潜力;A.const_get'K'=>cat.True,但是如果你试图重新定义一个常量,那么你会得到各种各样的警告,因此需要做额外的工作来取消定义,然后重新定义它,而不是仅仅分配一个变量。我不确定在Ruby中常量是否真的更快,因为它们在技术上仍然是变量——你可以在运行时读写它们。在编译语言中,编译器可以内联常量以加快速度,但在Ruby中,这将更加困难。@averell对任何类型的方法调用都会产生一个小的惩罚,但随着Ruby版本的发布,这种惩罚会减少。例如,由于内部优化,attr_reader生成的方法比手工编码的等效方法更快。在大多数情况下,这种惩罚是不相关的,但值得了解。@tadman-我以为我们讨论的是访问实例变量和访问常量,所以在这两种情况下都不涉及方法调用。不过,我同意常数可能存在一些优化潜力。