Ricerca…


Sintassi

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

Osservazioni

Le variabili di classe sono condivise nella gerarchia di classi. Ciò può comportare un comportamento sorprendente.

class A
  @@variable = :x

  def self.variable
    @@variable
  end
end

class B < A
  @@variable = :y
end

A.variable  # :y

Le classi sono oggetti, quindi è possibile utilizzare variabili di istanza per fornire lo stato specifico per ogni classe.

class A
  @variable = :x

  def self.variable
    @variable
  end
end

class B < A
  @variable = :y
end

A.variable  # :x

Variabili locali

Le variabili locali (a differenza delle altre classi variabili) non hanno alcun prefisso

local_variable = "local"
p local_variable
# => local

Il suo ambito dipende da dove è stato dichiarato, non può essere usato al di fuori dell'ambito "contenitori di dichiarazione". Ad esempio, se una variabile locale è dichiarata in un metodo, può essere utilizzata solo all'interno di quel metodo.

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'

Naturalmente, le variabili locali non sono limitate ai metodi, come una regola empirica si potrebbe dire che, non appena si dichiara una variabile all'interno di un do ... end blocco do ... end o racchiusa tra parentesi graffe {} , sarà locale e con scope il blocco è stato dichiarato in

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'

Tuttavia, le variabili locali dichiarate in if o case block possono essere utilizzate nello scope parent:

if true
    usable = "yay"
end

p usable
# yay
# => "yay"

Mentre le variabili locali non possono essere utilizzate al di fuori del suo blocco di dichiarazione, verranno passate ai blocchi:

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

Ma non alle definizioni metodo / classe / modulo

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'

Le variabili utilizzate per gli argomenti di blocco sono (ovviamente) locali al blocco, ma oscureranno le variabili precedentemente definite, senza sovrascriverle.

overshadowed = "sunlight"

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

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

Variabili di classe

Le variabili di classe hanno un ambito di classe, possono essere dichiarate ovunque nella classe. Una variabile sarà considerata una variabile di classe quando è preceduta da @@

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"

Le variabili di classe sono condivise tra classi correlate e possono essere sovrascritte da una classe figlia

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

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

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

Questo comportamento è indesiderato per la maggior parte del tempo e può essere aggirato utilizzando variabili di istanza a livello di classe.

Le variabili di classe definite all'interno di un modulo non sovrascriveranno le loro variabili di classe comprese le classi:

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

Variabili globali

Le variabili globali hanno una portata globale e, quindi, possono essere utilizzate ovunque. Il loro scopo non dipende da dove sono definiti. Una variabile sarà considerata globale, se preceduta da un segno $ .

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

Poiché una variabile globale può essere definita ovunque e sarà visibile ovunque, la chiamata a una variabile globale "non definita" restituirà nil anziché generare un errore.

p $undefined_var
# nil
# => nil

Sebbene le variabili globali siano facili da usare, il suo utilizzo è fortemente scoraggiato a favore delle costanti.

Variabili di istanza

Le variabili di istanza hanno un ambito a livello di oggetto, possono essere dichiarate ovunque nell'oggetto, tuttavia una variabile di istanza dichiarata a livello di classe, sarà visibile solo nell'oggetto classe. Una variabile sarà considerata una variabile di istanza quando è preceduta da @ . Le variabili di istanza vengono utilizzate per impostare e ottenere attributi di oggetti e restituiranno zero se non definite.

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"

Non è possibile accedere alla variabile di istanza dichiarata a livello di classe a livello di oggetto:

dino_1.try_to_speak
# => nil

Tuttavia, abbiamo usato la variabile di istanza @base_sound per istanziare il suono quando non viene passato alcun suono al nuovo metodo:

dino_1.speak
# => "rawwr"

Le variabili di istanza possono essere dichiarate ovunque nell'oggetto, anche all'interno di un blocco:

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

Le variabili di istanza non sono condivise tra istanze della stessa classe

dino_2.sound_length
# => nil

Questo può essere usato per creare variabili di livello di classe, che non verranno sovrascritte da una classe figlio, poiché le classi sono anche oggetti in 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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow