Поиск…


Синтаксис

  • $ global_variable
  • @@ class_variable
  • @instance_variable
  • local_variable

замечания

Переменные класса разделяются в иерархии классов. Это может привести к неожиданному поведению.

class A
  @@variable = :x

  def self.variable
    @@variable
  end
end

class B < A
  @@variable = :y
end

A.variable  # :y

Классы - это объекты, поэтому переменные экземпляра могут использоваться для предоставления состояния, специфичного для каждого класса.

class A
  @variable = :x

  def self.variable
    @variable
  end
end

class B < A
  @variable = :y
end

A.variable  # :x

Локальные переменные

Локальные переменные (в отличие от других классов переменных) не имеют префикса

local_variable = "local"
p local_variable
# => local

Его объем зависит от того, где он был объявлен, он не может использоваться вне области «контейнеры объявлений». Например, если локальная переменная объявлена ​​в методе, ее можно использовать только внутри этого метода.

def some_method
    method_scope_var = "hi there"
    p method_scope_var
end

some_method
# hi there
# => hi there

method_scope_var
# NameError: undefined local variable or method `method_scope_var'

Конечно, локальные переменные не ограничиваются методами, поскольку вы можете сказать, что, как только вы объявляете переменную внутри do ... end block или завернуты в фигурные скобки {} она будет локальной и скопирована в блок, в котором он был объявлен.

2.times do |n|
    local_var = n + 1
    p local_var
end
# 1
# 2
# => 2

local_var
# NameError: undefined local variable or method `local_var'

Однако локальные переменные, объявленные в блоках if или case могут использоваться в родительской области:

if true
    usable = "yay"
end

p usable
# yay
# => "yay"

Хотя локальные переменные не могут использоваться вне блока объявления, они будут переданы в блоки:

my_variable = "foo"

my_variable.split("").each_with_index do |char, i|
    puts "The character in string '#{my_variable}' at index #{i} is #{char}"
end
# The character in string 'foo' at index 0 is f
# The character in string 'foo' at index 1 is o
# The character in string 'foo' at index 2 is o
# => ["f", "o", "o"]

Но не для определения метода / класса / модуля

my_variable = "foo"

def some_method
    puts "you can't use the local variable in here, see? #{my_variable}"
end

some_method
# NameError: undefined local variable or method `my_variable'

Переменные, используемые для аргументов блока (конечно), являются локальными для блока, но будут затенять ранее определенные переменные, не перезаписывая их.

overshadowed = "sunlight"

["darkness"].each do |overshadowed|
    p overshadowed
end
# darkness
# => ["darkness"]

p overshadowed
# "sunlight"
# => "sunlight"

Переменные класса

Переменные класса имеют классный охват, они могут быть объявлены в любом месте класса. Переменная будет считаться переменной класса, если префикс с @@

class Dinosaur
    @@classification = "Like a Reptile, but like a bird"
    
    def self.classification
        @@classification
    end

    def classification
        @@classification
    end
end

dino = Dinosaur.new
dino.classification
# => "Like a Reptile, but like a bird"
  
Dinosaur.classification
# => "Like a Reptile, but like a bird"

Переменные класса разделяются между связанными классами и могут быть перезаписаны из дочернего класса

class TRex < Dinosaur
    @@classification = "Big teeth bird!"
end

TRex.classification
# => "Big teeth bird!"

Dinosaur.classification
# => "Big teeth bird!"

Это поведение нежелательно в большинстве случаев и может быть обойдено с использованием переменных экземпляра класса.

Переменные класса, определенные внутри модуля, не будут перезаписывать их включенные переменные класса классов:

module SomethingStrange
    @@classification = "Something Strange"
end

class DuckDinosaur < Dinosaur
    include SomethingStrange
end

DuckDinosaur.class_variables
# => [:@@classification]
SomethingStrange.class_variables
# => [:@@classification]

DuckDinosaur.classification
# => "Big teeth bird!"

Глобальные переменные

Глобальные переменные имеют глобальный масштаб и, следовательно, могут использоваться повсеместно. Их объем не зависит от того, где они определены. Переменная будет считаться глобальной, с префиксом знака $ .

$i_am_global = "omg"

class Dinosaur
    def instance_method
       p "global vars can be used everywhere. See? #{$i_am_global}, #{$another_global_var}" 
    end

    def self.class_method
       $another_global_var = "srsly?"
       p "global vars can be used everywhere. See? #{$i_am_global}"
    end
end

Dinosaur.class_method
# "global vars can be used everywhere. See? omg"
# => "global vars can be used everywhere. See? omg"

dinosaur = Dinosaur.new
dinosaur.instance_method
# "global vars can be used everywhere. See? omg, srsly?"
# => "global vars can be used everywhere. See? omg, srsly?"

Поскольку глобальная переменная может быть определена везде и будет видна повсюду, вызов глобальной неопределенной глобальной переменной будет возвращать нуль вместо повышения ошибки.

p $undefined_var
# nil
# => nil

Хотя глобальные переменные легко использовать, его использование сильно не рекомендуется в пользу констант.

Переменные экземпляра

Переменные экземпляра имеют объектную широкую область, они могут быть объявлены в любом месте объекта, однако переменная экземпляра, объявленная на уровне класса, будет видна только в объекте класса. Переменная будет считаться переменной экземпляра, если префикс с @ . Переменные экземпляра используются для установки и получения атрибутов объектов и возвращают нуль, если они не определены.

class Dinosaur
    @base_sound = "rawrr"

    def initialize(sound = nil)
        @sound = sound || self.class.base_sound
    end

    def speak
        @sound
    end

    def try_to_speak
        @base_sound
    end

    def count_and_store_sound_length
        @sound.chars.each_with_index do |char, i|
            @sound_length = i + 1
            p "#{char}: #{sound_length}"
        end
    end
    
    def sound_length
        @sound_length
    end

    def self.base_sound
        @base_sound
    end
end

dino_1 = Dinosaur.new
dino_2 = Dinosaur.new "grrr"

Dinosaur.base_sound
# => "rawrr"
dino_2.speak
# => "grrr"

Переменная экземпляра, объявленная на уровне класса, не может быть доступна на уровне объекта:

dino_1.try_to_speak
# => nil

Однако мы использовали переменную экземпляра @base_sound для создания экземпляра звука, когда звук не передается новому методу:

dino_1.speak
# => "rawwr"

Переменные экземпляра могут быть объявлены в любом месте объекта, даже внутри блока:

dino_1.count_and_store_sound_length
# "r: 1"
# "a: 2"
# "w: 3"
# "r: 4"
# "r: 5"
# => ["r", "a", "w", "r", "r"]

dino_1.sound_length
# => 5

Переменные экземпляра не разделяются между экземплярами одного и того же класса

dino_2.sound_length
# => nil

Это можно использовать для создания переменных уровня класса, которые не будут перезаписаны дочерним классом, поскольку классы также являются объектами в Ruby.

class DuckDuckDinosaur < Dinosaur
    @base_sound = "quack quack"
end

duck_dino = DuckDuckDinosaur.new
duck_dino.speak
# => "quack quack"
DuckDuckDinosaur.base_sound
# => "quack quack"
Dinosaur.base_sound
# => "rawrr"


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow