Приведенные переменные экземпляра причины для классов в Ruby состоят в том, что классы Ruby являются самими (экземпляры класса Class). Попробуйте сами, проверив DummyClass.class
. В языке C# в Ruby нет «статических методов», потому что каждый метод определен (или унаследован) каким-то экземпляром и вызывается в каком-то экземпляре. Соответственно, они могут получить доступ к любым переменным экземпляра, которые будут доступны для вызываемого абонента.
С DummyClass
- это экземпляр, он может иметь свои собственные переменные экземпляра просто отлично. Вы даже можете получить доступ к этим переменным экземпляра, если у вас есть ссылка на класс (который всегда должен быть указан потому, что имена классов являются константами). В любой момент вы сможете вызвать ::DummyClass.instance_variable_get(:@arr)
и получить текущее значение этой переменной экземпляра.
Что касается того, хорошо ли это делать, зависит от методов.
Если @arr
логически является «состоянием» экземпляра/класса DummyClass
, то сохраните его в переменной экземпляра. Если @arr
используется только в dummy_method2
в качестве оперативного ярлыка, передайте его в качестве аргумента. Чтобы привести пример использования подхода с переменной экземпляра, рассмотрите ActiveRecord в Rails. Это позволяет сделать это:
u = User.new
u.name = "foobar"
u.save
Здесь имя, которое было назначено пользователю данные, что законно на пользователя. Если перед вызовом #save
нужно было спросить «какое имя пользователя на этом этапе», вы ответите «foobar». Если вы копаете достаточно далеко во внутренностях (вы будете копать очень далеко и много метапрограммировать, вы обнаружите, что они используют переменные экземпляра именно для этого).
Пример, который я использовал, содержит два отдельных публичных вызова. Чтобы увидеть случай, когда переменные экземпляра все еще используются, несмотря на только один сделанный вызов, посмотрите на реализацию ActiveRecord #update_attributes
. Тело метода просто load(attributes, false) && save
.Почему #save
не получает никаких аргументов (например, новый name
), хотя он будет находиться в теле, где-то вроде UPDATE users SET name='foobar' WHERE id=1;
? Это потому, что такие вещи, как имя, являются информацией, которая принадлежит экземпляру.
И наоборот, мы можем посмотреть на случай, когда переменные экземпляра не имеют смысла использовать. Посмотрите на реализацию #link_to_if
, метод, который принимает аргумент boolean-ish (обычно это выражение в исходном коде) вместе с аргументами, которые обычно принимаются #link_to
, например URL-адрес для ссылки. Когда логическое условие является правдивым, необходимо передать остальные аргументы #link_to
и вызвать его. Было бы нецелесообразно назначать переменные экземпляра здесь, потому что вы не сказали бы, что вызывающий контекст здесь (средство визуализации) содержит эту информацию в экземпляре. В самом рендерере нет «ссылки для ссылки», и, следовательно, он не должен быть похоронен в переменной экземпляра.
Благодарим вас за это замечательное объяснение примерами, особенно о том, является ли это хорошей практикой или нет. – tackleberry