Ruby Language
Variabler Umfang und Sichtbarkeit
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"