Переменная экземпляра класса 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


Я понимаю теперь переменные экземпляра класса не передаются по цепочке наследования!

648   5  

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

    Ничего не найдено.