Экземпляр класса 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 доступны в единственном числе для страницы просмотра только потому, что я сделал ее переменной экземпляра в файле контроллера.