Sök…


Syntax

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

Anmärkningar

Klassvariabler delas i klasshierarkin. Detta kan resultera i överraskande beteende.

class A
  @@variable = :x

  def self.variable
    @@variable
  end
end

class B < A
  @@variable = :y
end

A.variable  # :y

Klasser är objekt, så instansvariabler kan användas för att ge tillstånd som är specifikt för varje klass.

class A
  @variable = :x

  def self.variable
    @variable
  end
end

class B < A
  @variable = :y
end

A.variable  # :x

Lokala variabler

Lokala variabler (till skillnad från de andra variabla klasserna) har inga prefix

local_variable = "local"
p local_variable
# => local

Omfånget är beroende av var det har deklarerats, det kan inte användas utanför "deklarationsbehållares" räckvidd. Om till exempel en lokal variabel deklareras i en metod kan den bara användas inuti den metoden.

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'

Naturligtvis är lokala variabler inte begränsade till metoder, som en tumregel kan du säga att så snart du förklarar en variabel inuti ett do ... end slutblock eller inslaget i lockiga hängslen {} kommer det att vara lokalt och scoped till det block som det har förklarats i.

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'

Lokala variabler som deklareras i if eller case block kan dock användas i överordnade omfång:

if true
    usable = "yay"
end

p usable
# yay
# => "yay"

Medan lokala variabler inte kan användas utanför dess deklarationsblock, kommer de att överföras till block:

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

Men inte definitioner av metod / klass / modul

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'

Variablerna som används för blockargument är (naturligtvis) lokala för blocket, men överskuggar tidigare definierade variabler utan att skriva över dem.

overshadowed = "sunlight"

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

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

Klassvariabler

Klassvariabler har ett klassbrett omfattning, de kan deklareras var som helst i klassen. En variabel kommer att betraktas som en klassvariabel när den är förinställd med @@

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"

Klassvariabler delas mellan relaterade klasser och kan skrivas över från en barnklass

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

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

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

Detta beteende är oönskat större delen av tiden och kan kringgås med hjälp av instansvariabler på klassnivå.

Klassvariabler definierade i en modul kommer inte att skriva över deras inkluderande klasser klassvariabler:

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

Globala variabler

Globala variabler har ett globalt omfång och kan därför användas överallt. Deras omfattning beror inte på var de definieras. En variabel kommer att betraktas som global när den är förinställd med ett $ -tecken.

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

Eftersom en global variabel kan definieras överallt och kommer att vara synlig överallt kommer en "odefinierad" global variabel att returnera noll istället för att ta upp ett fel.

p $undefined_var
# nil
# => nil

Även om globala variabler är enkla att använda, är användningen starkt avskräckt till förmån för konstanter.

Instansvariabler

Instansvariabler har ett objektbrett omfattning, de kan deklareras var som helst i objektet, men en instansvariabel som deklareras på klassnivå kommer bara att vara synlig i klassobjektet. En variabel kommer att betraktas som en instansvariabel när den är förinställd med @ . Instansvariabler används för att ställa in och få ett objektattribut och kommer att returnera noll om det inte är definierat.

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"

Den instansvariabel som deklarerats på klassnivå kan inte nås på objektnivå:

dino_1.try_to_speak
# => nil

Men vi använde instansvariabeln @base_sound att instansera ljudet när inget ljud skickas till den nya metoden:

dino_1.speak
# => "rawwr"

Instansvariabler kan deklareras var som helst i objektet, även i ett block:

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

Instansvariabler delas inte mellan instanser av samma klass

dino_2.sound_length
# => nil

Detta kan användas för att skapa klassnivåvariabler, som inte kommer att skrivas över av en barnklass, eftersom klasser också är objekt i 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow