Suche…


Syntax

  • $ global_variable
  • @@ class_variable
  • @Instanzvariable
  • lokale Variable

Bemerkungen

Klassenvariablen werden in der Klassenhierarchie gemeinsam genutzt. Dies kann zu überraschendem Verhalten führen.

class A
  @@variable = :x

  def self.variable
    @@variable
  end
end

class B < A
  @@variable = :y
end

A.variable  # :y

Klassen sind Objekte, daher können Instanzvariablen verwendet werden, um einen für jede Klasse spezifischen Status bereitzustellen.

class A
  @variable = :x

  def self.variable
    @variable
  end
end

class B < A
  @variable = :y
end

A.variable  # :x

Lokale Variablen

Lokale Variablen haben (im Gegensatz zu den anderen Variablenklassen) kein Präfix

local_variable = "local"
p local_variable
# => local

Ihr Geltungsbereich hängt davon ab, wo er deklariert wurde. Er kann nicht außerhalb des Geltungsbereichs "Deklarationscontainer" verwendet werden. Wenn beispielsweise eine lokale Variable in einer Methode deklariert ist, kann sie nur innerhalb dieser Methode verwendet werden.

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'

Natürlich sind lokale Variablen nicht auf Methoden beschränkt. Als Faustregel können Sie sagen, dass sobald Sie eine Variable innerhalb eines do ... end Blocks deklarieren oder in geschweifte Klammern {} diese lokal und in einem bestimmten Bereich liegt der Block, in dem es deklariert wurde.

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'

In if oder case Blöcken deklarierte lokale Variablen können jedoch im übergeordneten Bereich verwendet werden:

if true
    usable = "yay"
end

p usable
# yay
# => "yay"

Lokale Variablen können nicht außerhalb ihres Deklarationsblocks verwendet werden, sie werden jedoch an Blöcke übergeben:

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

Aber nicht zu Methoden- / Klassen- / Moduldefinitionen

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'

Die für Blockargumente verwendeten Variablen sind (natürlich) lokal für den Block, überschreiben jedoch zuvor definierte Variablen, ohne sie zu überschreiben.

overshadowed = "sunlight"

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

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

Klassenvariablen

Klassenvariablen haben einen Klassenweiten Gültigkeitsbereich. Sie können an einer beliebigen Stelle in der Klasse deklariert werden. Eine Variable wird als Klassenvariable betrachtet, wenn @@ vorangestellt @@

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"

Klassenvariablen werden von verwandten Klassen gemeinsam verwendet und können von einer untergeordneten Klasse überschrieben werden

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

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

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

Dieses Verhalten ist meistens unerwünscht und kann mithilfe von Instanzvariablen auf Klassenebene umgangen werden.

Klassenvariablen, die in einem Modul definiert sind, überschreiben nicht ihre Klassenklassen, einschließlich Klassenvariablen:

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 Variablen

Globale Variablen haben einen globalen Geltungsbereich und können daher überall verwendet werden. Ihr Umfang hängt nicht davon ab, wo sie definiert sind. Eine Variable wird als global betrachtet, wenn ein $ -Zeichen vorangestellt ist.

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

Da eine globale Variable überall definiert werden kann und überall sichtbar ist, gibt der Aufruf einer globalen Variablen "undefined" null zurück, anstatt einen Fehler zu melden.

p $undefined_var
# nil
# => nil

Obwohl globale Variablen einfach zu verwenden sind, wird die Verwendung von Konstanten dringend empfohlen.

Instanzvariablen

Instanzvariablen haben einen objektweiten Gültigkeitsbereich. Sie können an einer beliebigen Stelle im Objekt deklariert werden. Eine auf Klassenebene deklarierte Instanzvariable ist jedoch nur im Klassenobjekt sichtbar. Eine Variable wird als Instanzvariable betrachtet, wenn @ vorangestellt ist. Instanzvariablen werden zum Festlegen und Abrufen von Objektattributen verwendet und geben Null zurück, wenn sie nicht definiert sind.

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"

Auf die auf Klassenebene deklarierte Instanzvariable kann nicht auf Objektebene zugegriffen werden:

dino_1.try_to_speak
# => nil

Wir haben jedoch die Instanzvariable @base_sound , um den Sound zu instanziieren, wenn kein Sound an die neue Methode übergeben wird:

dino_1.speak
# => "rawwr"

Instanzvariablen können irgendwo im Objekt deklariert werden, sogar innerhalb eines Blocks:

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

Instanzvariablen werden nicht von Instanzen derselben Klasse gemeinsam genutzt

dino_2.sound_length
# => nil

Dies kann zum Erstellen von Klassenebenenvariablen verwendet werden, die nicht von einer untergeordneten Klasse überschrieben werden, da Klassen auch Objekte in Ruby sind.

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow