Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Ruby中何时使用常量而不是实例变量?_Ruby_Variables_Instance_Constants - Fatal编程技术网

在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-我以为我们讨论的是访问实例变量和访问常量,所以在这两种情况下都不涉及方法调用。不过,我同意常数可能存在一些优化潜力。