Szukaj…


Składnia

  • $ zmienna_globalna
  • @@ zmienna_klasy
  • @instance_variable
  • zmienna_lokalna

Uwagi

Zmienne klas są współdzielone w hierarchii klas. Może to spowodować zaskakujące zachowanie.

class A
  @@variable = :x

  def self.variable
    @@variable
  end
end

class B < A
  @@variable = :y
end

A.variable  # :y

Klasy są obiektami, więc zmiennych instancji można użyć do zapewnienia stanu specyficznego dla każdej klasy.

class A
  @variable = :x

  def self.variable
    @variable
  end
end

class B < A
  @variable = :y
end

A.variable  # :x

Zmienne lokalne

Zmienne lokalne (w przeciwieństwie do innych klas zmiennych) nie mają żadnego prefiksu

local_variable = "local"
p local_variable
# => local

Jego zakres zależy od miejsca, w którym został zadeklarowany, nie można go używać poza zakresem „kontenerów deklaracji”. Na przykład, jeśli zmienna lokalna jest zadeklarowana w metodzie, można jej użyć tylko wewnątrz tej metody.

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'

Oczywiście zmienne lokalne nie są ograniczone do metod, z reguły można powiedzieć, że gdy tylko zadeklarujesz zmienną w bloku do ... end lub owiniętym w nawiasy klamrowe {} , będzie ona lokalna i będzie miała zasięg blok, w którym został zadeklarowany.

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'

Jednak zmienne lokalne zadeklarowane w blokach if lub case mogą być używane w zakresie nadrzędnym:

if true
    usable = "yay"
end

p usable
# yay
# => "yay"

Chociaż zmiennych lokalnych nie można używać poza jego blokiem deklaracji, zostaną one przekazane do bloków:

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"]

Ale nie do definicji metody / klasy / modułu

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'

Zmienne używane do argumentów blokowych są (oczywiście) lokalne dla bloku, ale przyćmią wcześniej zdefiniowane zmienne, nie nadpisując ich.

overshadowed = "sunlight"

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

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

Zmienne klasy

Zmienne klasy mają zakres obejmujący całą klasę, można je zadeklarować w dowolnym miejscu w klasie. Zmienna będzie uważana za zmienną klasową, gdy będzie poprzedzona @@

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"

Zmienne klas są wspólne dla pokrewnych klas i mogą zostać zastąpione klasami potomnymi

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

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

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

To zachowanie jest niepożądane przez większość czasu i można je obejść, używając zmiennych instancji na poziomie klasy.

Zmienne klas zdefiniowane w module nie nadpisują ich, włączając w to zmienne klas klas:

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!"

Zmienne globalne

Zmienne globalne mają zasięg globalny i dlatego można ich używać wszędzie. Ich zakres nie zależy od tego, gdzie są zdefiniowane. Zmienna będzie uważana za globalną, jeśli będzie poprzedzona znakiem $ .

$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?"

Ponieważ zmienna globalna może być zdefiniowana wszędzie i będzie widoczna wszędzie, wywołanie „niezdefiniowanej” zmiennej globalnej zwróci zero zamiast zgłaszania błędu.

p $undefined_var
# nil
# => nil

Chociaż zmienne globalne są łatwe w użyciu, zdecydowanie nie zaleca się ich używania na rzecz stałych.

Zmienne instancji

Zmienne instancji mają szeroki zakres obiektu, można je zadeklarować w dowolnym miejscu obiektu, jednak zmienna instancji zadeklarowana na poziomie klasy będzie widoczna tylko w obiekcie klasy. Zmienna będzie uważana za zmienną instancji, gdy będzie poprzedzona znakiem @ . Zmienne instancji są używane do ustawiania i pobierania atrybutów obiektów i zwracają zero, jeśli nie są zdefiniowane.

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"

Do zmiennej instancji zadeklarowanej na poziomie klasy nie można uzyskać dostępu na poziomie obiektu:

dino_1.try_to_speak
# => nil

Jednak użyliśmy zmiennej instancji @base_sound aby utworzyć instancję dźwięku, gdy żaden dźwięk nie zostanie przekazany do nowej metody:

dino_1.speak
# => "rawwr"

Zmienne instancji można zadeklarować w dowolnym miejscu obiektu, nawet w bloku:

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

Zmienne instancji nie są współużytkowane między instancjami tej samej klasy

dino_2.sound_length
# => nil

Można tego użyć do tworzenia zmiennych na poziomie klasy, które nie zostaną nadpisane przez klasę potomną, ponieważ klasy są również obiektami w Rubim.

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow