Экземпляр класса 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 процентов переменных в вашем приложения, так что это хорошая идея, чтобы быть знакомы с ними.
как следует из названия, переменные экземпляра доступны для конкретного экземпляра. Существует определенный синтаксис для установки переменных экземпляра, вам нужно использовать @ знак для определения переменной. Вот реальный пример из моей собственной работы:--4-->
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. Эта переменная создается в методе индекс и недоступна для других методов в файле. Теперь, почему я просто не сделал эту локальную переменную, так как она недоступна для других методов в классе?
причина этого в том, что рельсы построен таким образом, что посмотреть и контроллер файлы подключены для связи друг с другом, поэтому эта переменная экземпляра @portfolio_items можно получить доступ в связанном посмотреть файл, как Итак:
<%= 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 доступны в единственном числе для страницы просмотра только потому, что я сделал ее переменной экземпляра в файле контроллера.