こんにちは!ゆきまさです!!(@yyykms)
Rubyには文字列のようなシンボルと呼ばれるクラスがあります。
よくハッシュに使用されたりするので、シンボルと文字列の違いをしっかり理解しておく必要があります。
そこで今回は、このシンボルについて詳しく紹介していきますのでぜひ参考にしていってください!
シンボルとは
公式ドキュメントでは次のように説明しています。
シンボルを表すクラス。シンボルは任意の文字列と一対一に対応するオブジェクトです。
文字列の代わりに用いることもできますが、必ずしも文字列と同じ振る舞いをするわけではありません。同じ内容のシンボルは必ず同一のオブジェクトです。Rubyの内部実装では、メソッド名や変数名、定数名、クラス名など の`名前’を整数で管理しています。これは名前を直接文字列として処理するよりも 速度面で有利だからです。そしてその整数をRubyのコード上で表現したものがシンボルです。
シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。
名前を管理するという役割上、シンボルと文字列は一対一に対応します。 また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。
Ruby 2.6.0 リファレンスマニュアル より
簡単にまとめると
- 文字列は同じ内容でもオブジェクトIDが異なるがシンボルは同一となる
- ソース上では文字列のように見えているが、内部的には整数として扱われている
- 文字列と違って変更ができない
ということみたいですね。
シンボルの書き方
文字列は「'Ruby'」のように '(シングルクォート)もしくは "(ダブルクォート)で囲みますが、シンボルは「:Ruby」というように:(コロン)から始まります。
# シンボル
:Ruby
# 文字列
'Ruby'
シンボルと文字列の違い
では先ほどシンボルはどういうのもかを説明しましたが、結局よくわからないって方が多いと思います。
- オブジェクトIDが同一って何?
- 内部的に整数で扱われるってどういうこと?
- 変更できないの?
って疑問があるかと思うので、この辺りも説明していきます。
SymbolクラスとStringクラス
そもそもシンボルと文字列はクラスが違います。
シンボルはSymbol
クラスのオブジェクトで、文字列はString
クラスのオブジェクトなのです。
puts :Ruby.class #=> Symbol
puts 'Ruby'.class #=> String
処理速度
シンボルは内部で整数として管理されるため、文字列と比べて高速に処理できます。
実際にどのぐらい違うのかは詳しく調査できていないのですが、先ほどのリファレンスでは記述されていましたね。
Rubyの内部実装では、メソッド名や変数名、定数名、クラス名など の`名前’を整数で管理しています。これは名前を直接文字列として処理するよりも 速度面で有利だからです。
Ruby 2.6.0 リファレンスマニュアル より
# この例だと差は無いが、シンボルの方が早く処理できる
p 'シンボル' if :Ruby == :Ruby
p '文字列' if 'Ruby' == 'Ruby'
同じシンボルであればオブジェクトも同じ
文字列と違い、同じ内容のシンボルは必ず同一のオブジェクトとなります。
オブジェクトが同一ということは、オブジェクトの数が増えないのでメモリの使用効率がよくなります。
# シンボルは同一のオブジェクト
puts :Ruby.object_id #=> 989668
puts :Ruby.object_id #=> 989668
puts :Ruby.object_id #=> 989668
# 文字列は異なるオブジェクト
puts 'Ruby'.object_id #=> 70270585805660
puts 'Ruby'.object_id #=> 70270585805600
puts 'Ruby'.object_id #=> 70270585805540
シンボルはimmutable(イミュータブル)
シンボルはimmutable(変更不可)なオブジェクトのため、文字列のように破壊的な変更ができません。
なので、メッソド名などの「変更できない名前をつける」という用途に向いています。
# シンボルはimmutableなので、破壊的な変更は不可能
symbol = :Ruby
puts symbol.upcase!
#=> undefined method `upcase!' for :Ruby:Symbol (NoMethodError)
# 文字列は破壊的な変更が可能
string = 'Ruby'
puts string.upcase!
#=> RUBY
何に使うの?
ではここまで読んで、「シンボルとは?」「文字列との違いは?」という疑問は解消できたかと思いますので、用途について説明します。
主な用途
- ハッシュのキー
- クラス名/メソッド名/変数名/定数名
- ステータス名
これらは文字列自体がデータではないのでシンボルを使うと良いです。
文字列は「氏名」や「住所」など、文字列自体がデータであるときに使いますが、メソッド名やハッシュのキーなどはそれら自体にデータを必要としません。
そのため、文字列自体にデータを必要としない場合にシンボルが多く使用されています。
まとめ
では最後に簡単にまとめます。
- 文字列とは違うが似ているため、プログラマにとって理解しやすい
- 内部で整数として扱っているため、文字列に比べて処理速度が速い
- 同じ内容のシンボルは必ず同一のオブジェクトとなるため、メモリの使用効率が良い
- immutableなので、勝手に値を変えられない
- 文字列自体にデータを必要としない場合に多く使用される
ということで以上がシンボルについてでした!
「シンボルっていう文字列みたいなものがあるんだ」と思っていただけの人は、シンボルについてちゃんと知ることができたかと思います。
自分もその1人でした笑
この記事が参考になったのであれば幸いです!