I understand that instance variables are mean to be states, and constants are meant to be constant. Is there any reason (besides convention) to use a constant instead of an instance variable? Is there a memory/speed advantage to using constants?
There's a few things to consider here:
The best kind of constants are those that don't really change short of updating the software:
class ExampleClass
STATES = %i[
off
on
broken
].freeze
end
Generally you use these constants internally in the class and avoid sharing them. When you share them you're limited in how they're used. For example, if another class referenced ExampleClass::STATES
then you can't change that structure without changing other code.
You can make this more abstract by providing an interface :
class ExampleClass
def self.states
STATES
end
end
If you change the structure of that constant in the future you can always preserve the old behaviour:
class ExampleClass
STATES = {
on: 'On',
off: 'Off',
broken: 'Broken'
}.freeze
def self.states
STATES.keys
end
end
When you're talking about instance variables you mean things you can configure:
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
Constants are great in that they're defined once and used for the duration of the process, so technically they're faster. Instance variables are still pretty quick, and are often a necessity as illustrated above.
Constants, unlike instance variables, are global. And they will at least complain if you try to re-assign their value.
While there might be a theoretical difference in memory/speed, it will be irrelevant in practice.
You may not realize this, but classes and modules are considered constants.
pry(main)> Foo
NameError: uninitialized constant Foo
The best advice I can give as to when you should use constants are when they are exactly that, constant. For example, if I was making a scope in rails to find all the of recent Foo
s for instance, I would create a constant that shows what recent is.
class Foo < ActiveRecord::Base
DAYS_TILL_OLD = 7.days
scope :recent, -> { where "created_at > ?", DateTime.now - DAYS_TILL_OLD }
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.