Die Programmiersprache Ruby

Blog| Forum| Wiki  

Inhaltsverzeichnis

Allgemein

Das Symbol (z.B. :ruby, beachte den Doppelpunkt) ist ein spezielles Ruby-Objekt. Ein Symbol wird, egal wie oft es referenziert wird, nur ein einziges Mal im Speicher vorhanden sein. Das bedeutet, dass jedes Symbol eine einmalige Objektnummer hat:

1
2
3
4
:ruby.object_id #=> 111378
"ruby".object_id #=> 50370950
:ruby.object_id #=> 111378
"ruby".object_id #=> 50367100

Will man also ein Objekt nur identifizieren, ohne, dass es um den Inhalt des "Identifikators" geht, so ist ein Symbol einem anderen Objekt vorzuziehen, da dieses Symbol nur ein einziges Mal im gesamten Programm vorhanden ist und sich nie verändert. Beliebtestes Beispiel ist der Hash. Meistens werden Strings als Schlüssel benutzt - und jedes Mal, wenn der so mit einem Schlüssel versehene Wert aus dem Hash abgerufen wird, wird eine neue Instanz der Klasse String erzeugt, obwohl man eigentlich denselben String meinte, der als Schlüssel verwendet wurde.

1
2
3
4
h1 = {"k1" => 1, "k2" => 2} #Hier werden die Strings "k1" und "k2" erzeugt. 
h1["k1"] #Hier wird der String "k1" erneut erzeugt, als V��LLIG NEUES Objekt. 
h2 = {:k1 => 1, :k2 => 2} #Hier werden die Symbole :k1 und :k2 erzeugt. 
h2[:k1] #Hier wird erneut :k1 abgerufen - aber es ist DASSELBE :k1 wie eine Zeile hierdr��ber.

Strings lassen sich in Symbole konvertieren und umgekehrt; dafür werden die Methoden String#to_sym und Symbol#to_s (bzw. Symbol#id2name) sowie eine Substitutionssyntax benutzt:

1
2
3
4
5
6
7
8
"ruby".to_sym #=> :ruby
:ruby.to_s #=> "ruby"
@var = "foo"
:"@#{@var}" 
#=> :@foo
:ruby.to_i #=> 111378 #Hier dasselbe wie ein Aufruf von object_id
#Auch m��glich: 
%s{ruby} #=> :ruby

Gefahren

Trotz oder gerade wegen ihrer Einmaligkeit im Programm gibt es auch Gefahren beim Gebrauch von Symbolen. Wenn Symbole z.B. über eine Schleife endlos generiert werden, führt dies wie jede andere generierende Endlos- oder Langdauerschleife, ob mit eval, String#to_sym oder sonstwie zu einer Überfüllung des Speichers. Bei Symbolen besonders gefährlich ist die Tatsache, dass Symbole, eben aufgrund ihrer Einzigartigkeit auch bei Nicht-Referenzierung, nicht vom GC entfernt werden. Bei folgendem Beispiel wird klar, wie dieses Problem auftreten kann:

1
2
3
4
5
6
7
8
#Beispiel mit einem lang laufenden Server: 
while user = getname #Mit Strings
  # dobedobedo
end
#-----------------------------------------------
while user = getname.to_sym #Mit Symbolen
  # dobedobedo
end

Im ersten Fall wird der zur Identifizierung genutzte String nach Benutzung vom GC entfernt - im zweiten nicht, da der GC ja keine Symbole "wegräumt".

Kurzgefasst

Am Anfang ist es meist schwer zu verstehen, wann man ein Symbol verwenden soll und wann einen String. Als Faustregel kann man folgendes nehmen:
Ist der Inhalt des Objekts wichtig, nutze einen String. Ist die Identifikation eines Objekts wichtig, nutze ein Symbol, achte aber auf die Gefahren bei großen Mengen insbesondere generierter Symbole.

Änderungen an Symbol zu 1.9.1

  • Symbol#to_i wurde entfernt. Stattdessen muss man jetzt immer Symbol#object_id verwenden.
1
2
puts :ruby.to_i #=> NoMethodError
puts :ruby.object_id #=> 139400


Siehe auch