Zoeken…


Syntaxis

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

Opmerkingen

Klasse variabelen worden gedeeld in de klasse hiërarchie. Dit kan leiden tot verrassend gedrag.

class A
  @@variable = :x

  def self.variable
    @@variable
  end
end

class B < A
  @@variable = :y
end

A.variable  # :y

Klassen zijn objecten, dus instantievariabelen kunnen worden gebruikt om een status te geven die specifiek is voor elke klasse.

class A
  @variable = :x

  def self.variable
    @variable
  end
end

class B < A
  @variable = :y
end

A.variable  # :x

Lokale variabelen

Lokale variabelen hebben (in tegenstelling tot de andere variabeleklassen) geen voorvoegsel

local_variable = "local"
p local_variable
# => local

Het bereik is afhankelijk van waar het is aangegeven, het kan niet worden gebruikt buiten het bereik van de "aangiftecontainers". Als een lokale variabele bijvoorbeeld in een methode wordt gedeclareerd, kan deze alleen binnen die methode worden gebruikt.

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'

Lokale variabelen zijn natuurlijk niet beperkt tot methoden, als vuistregel zou je kunnen zeggen dat, zodra je een variabele in een do ... end eindblok of gewikkeld in accolades {} declareert, deze lokaal is en geschikt voor het blok waarin het is aangegeven.

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'

Lokale variabelen die zijn gedeclareerd in if of case blokken kunnen echter worden gebruikt in het bovenliggende bereik:

if true
    usable = "yay"
end

p usable
# yay
# => "yay"

Hoewel lokale variabelen niet buiten het aangifteblok kunnen worden gebruikt, worden deze doorgegeven aan blokken:

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

Maar niet op de definities van methoden / klassen / modules

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'

De variabelen die worden gebruikt voor blokargumenten zijn (natuurlijk) lokaal voor het blok, maar zullen eerder gedefinieerde variabelen overschaduwen, zonder ze te overschrijven.

overshadowed = "sunlight"

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

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

Klasse variabelen

Klasse variabelen hebben een klasse breed bereik, ze kunnen overal in de klasse worden gedeclareerd. Een variabele wordt beschouwd als een klassenvariabele wanneer deze wordt voorafgegaan door @@

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"

Klasse variabelen worden gedeeld tussen gerelateerde klassen en kunnen worden overschreven vanuit een onderliggende klasse

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

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

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

Dit gedrag is meestal ongewenst en kan worden omzeild door instantievariabelen op klassenniveau te gebruiken.

Klasse variabelen die in een module zijn gedefinieerd, overschrijven hun klassenklasse variabelen niet:

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

Globale variabelen

Globale variabelen hebben een globaal bereik en kunnen daarom overal worden gebruikt. Hun reikwijdte is niet afhankelijk van waar ze zijn gedefinieerd. Een variabele wordt als globaal beschouwd als deze wordt voorafgegaan door een $ -teken.

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

Omdat een globale variabele overal kan worden gedefinieerd en overal zichtbaar zal zijn, zal het aanroepen van een "niet-gedefinieerde" globale variabele nul zijn in plaats van een fout te veroorzaken.

p $undefined_var
# nil
# => nil

Hoewel globale variabelen gemakkelijk te gebruiken zijn, wordt het gebruik ervan ten zeerste afgeraden ten gunste van constanten.

Instantievariabelen

Instantievariabelen hebben een objectbreed bereik, ze kunnen overal in het object worden gedeclareerd, maar een instantievariabele die op klassenniveau wordt gedeclareerd, is alleen zichtbaar in het klasseobject. Een variabele wordt beschouwd als een instantievariabele wanneer deze wordt voorafgegaan door @ . Instantievariabelen worden gebruikt om objectenattributen in te stellen en op te halen en retourneren nul indien niet gedefinieerd.

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"

De instantievariabele die op klassenniveau is gedeclareerd, is niet toegankelijk op objectniveau:

dino_1.try_to_speak
# => nil

We hebben echter de instantievariabele @base_sound om het geluid te instantiëren wanneer er geen geluid wordt doorgegeven aan de nieuwe methode:

dino_1.speak
# => "rawwr"

Instantievariabelen kunnen overal in het object worden gedeclareerd, zelfs binnen een blok:

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

Instantievariabelen worden niet gedeeld tussen instanties van dezelfde klasse

dino_2.sound_length
# => nil

Dit kan worden gebruikt om variabelen op klassenniveau te maken die niet door een kindklasse worden overschreven, omdat klassen ook objecten in Ruby zijn.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow