Ответ 1
Последнее лучше. Если бы это был метод, новый массив и новые строки будут создаваться каждый раз, когда он вызывается, что является пустой тратой ресурсов.
Я реализовал форму, содержащую стробированную выпадающую таблицу для коллекции, и мне было интересно, что будет лучшим решением, я знаю, что оба способа, описанные ниже, работают, но я сделал следующее:
class Example
# Options for Example.
self.options
[ 'Yes', 'No', 'Not sure' ]
end
end
который вызывается Example.options
, но я знаю, что можно сделать следующее:
class Example
# Options for Example.
OPTIONS = [ 'Yes', 'No', 'Not sure' ]
end
который будет вызываться с помощью Example::OPTIONS
.
Вопрос в том, является ли любой из них хорошим способом или это просто не имеет значения вообще?
Последнее лучше. Если бы это был метод, новый массив и новые строки будут создаваться каждый раз, когда он вызывается, что является пустой тратой ресурсов.
TL; DR: Это зависит. Используются ли значения вне класса? Могут ли они стать динамичными? Могут ли они измениться для подклассов?
Как писал @sawa, недостаток метода (написанный таким образом) заключается в том, что каждый новый массив и строки создаются каждый раз.
Лучший способ написать это:
class Example
def self.options
@options ||= ['Yes', 'No', 'Not sure']
end
end
Массив хранится в переменной экземпляра @options
, чтобы избежать создания нового массива каждый раз.
Написанный таким образом метод очень похож на константу.
Одно ключевое различие заключается в том, что если Example
является подклассом, более естественно уточнить метод options
, чем константа options
:
class Parent < Example
def self.options
@options ||= [*super, 'Extra']
end
end
Сделать что-то подобное с константами сложно. Представьте, что ваш список параметров используется в методе класса, это будет выглядеть так:
class Example
OPTIONS = ['Yes', 'No', 'Not sure']
def self.foo(arg)
puts "Available options:",
self::OPTIONS # The self:: is needed here
# ...
end
end
class Parent < Example
OPTIONS = [*superclass::OPTIONS, 'Extra']
end
Трудная вещь о константах состоит в том, что self::OPTIONS
и options
не всегда одинаковы, а self.options
и options
одинаковы. Константы обычно используются без указания области (например, options
вместо self::OPTIONS
), и наследование просто не будет работать в этом случае.
Обратите внимание, что этот метод дает возможность сделать динамический результат (т.е. возвращать разные результаты в зависимости от других обстоятельств) без изменения API.
Заключительное примечание: я бы рекомендовал вызывать freeze
в вашем массиве, чтобы никто не изменял его.
Что я обычно делаю, так это сочетание вышеупомянутых методов:
class Player
JURISDICTIONS = %i(de uk ru)
def self.jurisdictions
JURISDICTIONS
end
end
У него есть несколько преимуществ:
Player.jurisdictions
вместо Player::JURISDICTIONS
).IMHO, производительность здесь не имеет значения.
Обновление:
Константа может быть скрыта с помощью метода private_constant
(http://ruby-doc.org/core-2.3.0/Module.html#method-i-private_constant)
Чтобы уточнить предложение Артура, я бы пошел с переменной класса, чтобы скрыть видимость константы.
class Player
@@jurisdictions = %i(de uk ru)
def self.jurisdictions
@@jurisdictions
end
end