Переменная экземпляра класса Ruby и переменная класса
Я читал "когда устанавливаются переменные экземпляра Ruby?"но у меня два мнения, когда использовать переменные экземпляра класса.
переменные класса являются общими для всех объектов класса, переменные экземпляра относятся к одному объекту. Там не так много места осталось для использования переменных экземпляра класса, если у нас есть переменные класса.
может кто-нибудь объяснить разницу между этими двумя и когда их использовать?
вот пример кода:
class S
@@k = 23
@s = 15
def self.s
@s
end
def self.k
@@k
end
end
p S.s #15
p S.k #23
Я понимаю теперь переменные экземпляра класса не передаются по цепочке наследования!
5 ответов:
переменная экземпляра класса:
class Parent @things = [] def self.things @things end def things self.class.things end end class Child < Parent @things = [] end Parent.things << :car Child.things << :doll mom = Parent.new dad = Parent.new p Parent.things #=> [:car] p Child.things #=> [:doll] p mom.things #=> [:car] p dad.things #=> [:car]переменные класса:
class Parent @@things = [] def self.things @@things end def things @@things end end class Child < Parent end Parent.things << :car Child.things << :doll p Parent.things #=> [:car,:doll] p Child.things #=> [:car,:doll] mom = Parent.new dad = Parent.new son1 = Child.new son2 = Child.new daughter = Child.new [ mom, dad, son1, son2, daughter ].each{ |person| p person.things } #=> [:car, :doll] #=> [:car, :doll] #=> [:car, :doll] #=> [:car, :doll] #=> [:car, :doll]с переменной экземпляра в классе (не на экземпляре этого класса) вы можете хранить что-то общее для этого класса, не имея подклассов автоматически также получить их (и наоборот). С переменными класса у вас есть удобство не писать
self.classиз объекта экземпляра, и (когда это желательно) вы также получаете автоматический обмен по всему классу иерархия.
слияния их вместе в один пример, который также покрывает переменные экземпляра в случаях:
class Parent @@family_things = [] # Shared between class and subclasses @shared_things = [] # Specific to this class def self.family_things @@family_things end def self.shared_things @shared_things end attr_accessor :my_things def initialize @my_things = [] # Just for me end def family_things self.class.family_things end def shared_things self.class.shared_things end end class Child < Parent @shared_things = [] endи затем в действии:
mama = Parent.new papa = Parent.new joey = Child.new suzy = Child.new Parent.family_things << :house papa.family_things << :vacuum mama.shared_things << :car papa.shared_things << :blender papa.my_things << :quadcopter joey.my_things << :bike suzy.my_things << :doll joey.shared_things << :puzzle suzy.shared_things << :blocks p Parent.family_things #=> [:house, :vacuum] p Child.family_things #=> [:house, :vacuum] p papa.family_things #=> [:house, :vacuum] p mama.family_things #=> [:house, :vacuum] p joey.family_things #=> [:house, :vacuum] p suzy.family_things #=> [:house, :vacuum] p Parent.shared_things #=> [:car, :blender] p papa.shared_things #=> [:car, :blender] p mama.shared_things #=> [:car, :blender] p Child.shared_things #=> [:puzzle, :blocks] p joey.shared_things #=> [:puzzle, :blocks] p suzy.shared_things #=> [:puzzle, :blocks] p papa.my_things #=> [:quadcopter] p mama.my_things #=> [] p joey.my_things #=> [:bike] p suzy.my_things #=> [:doll]
Я считаю главным (только?) отличается наследование:
class T < S end p T.k => 23 S.k = 24 p T.k => 24 p T.s => nilпеременные класса являются общими для всех "экземпляров класса" (т. е. подклассов), в то время как переменные экземпляра класса специфичны только для этого класса. Но если вы никогда не собираетесь расширять свой класс, разница чисто академическая.
#переменная экземпляра класса доступна только для метода класса, а не для методов экземпляра, тогда как переменная класса доступна как для методов экземпляра, так и для методов класса. Переменные экземпляра класса теряются в цепочке наследования, тогда как переменные класса не.
class Vars @class_ins_var = "class instance variable value" #class instance variable @@class_var = "class variable value" #class variable def self.class_method puts @class_ins_var puts @@class_var end def instance_method puts @class_ins_var puts @@class_var end end Vars.class_method puts "see the difference" obj = Vars.new obj.instance_method class VarsChild < Vars end VarsChild.class_method
как говорили другие, переменные класса разделяются между данным классом и его подклассами. Переменные экземпляра класса принадлежат ровно одному классу; его подклассы разделены.
Почему такое поведение существует? Ну, все в Ruby является объектом-даже классы. Это означает, что каждый класс имеет объект класса
Class(точнее, подклассClass), которая ей соответствует. (Когда вы говоритеclass Foo, вы действительно объявляете константуFooи присвоение объекта класса оно.) И каждый объект Ruby может иметь переменные экземпляра, поэтому объекты класса также могут иметь переменные экземпляра.проблема в том, что переменные экземпляра на объектах класса на самом деле не ведут себя так, как вы обычно хотите, чтобы переменные класса вели себя. Обычно вы хотите, чтобы переменная класса, определенная в суперклассе, была совместно использована с его подклассами, но это не так, как работают переменные экземпляра-подкласс имеет свой собственный объект класса, и этот объект класса имеет свои собственные переменные экземпляра. Так они и познакомились отдельные переменные класса с поведением, которое вы, скорее всего, захотите.
другими словами, переменные экземпляра класса являются своего рода случайностью дизайна Ruby. Вы, вероятно, не должны использовать их, если вы специально не знаете, что они то, что вы ищете.
Итак, как вы знаете, переменная класса-это переменные, доступные для определенного класса, и синтаксис выглядит так:
class myClass @@teams = ["A's","Tigers"] endоднако вы редко будете использовать переменные класса в реальных приложениях, потому что вы можете сделать то же самое с помощью локальных или переменных экземпляра. Нет ничего плохого, если вы используете переменные класса, но его обычно не используют большинство разработчиков. На самом деле, локальные переменные и переменные экземпляра, скорее всего, составляют более 98 процентов переменных в вашем приложения, так что это хорошая идея, чтобы быть знакомы с ними.
как следует из названия, переменные экземпляра доступны для конкретного экземпляра. Существует определенный синтаксис для установки переменных экземпляра, вам нужно использовать @ знак для определения переменной. Вот реальный пример из моей собственной работы:
class PortfolioController < ApplicationController before_action :set_portfolio_item, only: [:edit, :update, :show, :destroy] layout 'portfolio' access all: [:show, :index, :angular], user: {except: [:destroy, :new, :create]} def index # this calls the model @portfolio_items = Portfolio.by_position end endВ этом коде вы можете видеть, что есть экземпляр переменной с именем @portfolio_items. Эта переменная создается в методе индекс и не доступна для других методов в файле. Теперь, почему я просто не сделал это локальной переменной, так как она недоступна для других методов в классе?
причина этого в том, что рельсы построен таким образом, что view и контроллер файлы подключены для связи друг с другом, поэтому эта переменная экземпляра @portfolio_items можно получить доступ в соответствующем view файл, как Итак:
<%= form_for(@portfolio_item) do |f| %> <% if @portfolio_item.errors.any? %> <% @portfolio_item.errors.full_messages.each do |error| %> <% alert_generator error %> <% end %> <% end %>Теперь @portfolio_items доступны в единственном числе для страницы просмотра только потому, что я сделал его переменной экземпляра в файле контроллера.
Comments