経緯
こないだ仕事で同僚のPRをレビューしていた際に定数が使われていて、ふと、何のために定数を使っているのか気になった。
それで定数ついて軽く調べてみた。
そもそも定数とは?
僕の前提知識としては
定数 = (一般的には)代入した後、変更できなく一つのオブジェクトを指すよう固定されたもの。
でもRubyの定数は確か違うっていう曖昧な理解をしていた。
Rubyにおいての書き方は大文字からはじまる識別子。
ex) Constant
, CONSTANT
定数を調べてみたところ、wikipediaによると
変数同様プログラムのソースコードにおいて、扱われるデータを一定期間記憶し必要なときに利用できるようにするために、データに固有の名前を与えたものである。 ただし変数とは異なり、一度初期化するとその内容(値)を変更することはできない。よって、内容が変化しないことが保証される名前が必要なときに使用される。
なるほど、やっぱ一度定義したら変更できないのね。
つまり、イミュータブルで再代入もできないってことか。
でRubyでは?
irbで見てみた。
CONSTANT = "constant"
=> "constant"
# まずイミュータブルかどうか
CONSTANT.upcase!
=> "CONSTANT"
CONSTANT
=> "CONSTANT"
# 普通に変更できてる。
# 次に再代入できるか
CONSTANT = "can_be_reassigned?"
(irb):4: warning: already initialized constant CONSTANT
(irb):1: warning: previous definition of CONSTANT was here
=> "can_be_reassigned?"
CONSTANT
=> "can_be_reassigned?"
# warningが出るが再代入できてる。
結論
結局、変数と定数の違いは下記のようなものか。
1.スコープ
定数はClass::CONSTANT
のような形で定義元のclassの外でも呼べる。
変数については種類によってスコープが様々だが。
2.継承やインクルードができるか
classやmoduleの定義には定数が使われてるので。
ってことで、
本来の一般的な定数の
「内容が変化しない」ってその性質は持ち合わせておらず、可変性においては変数とほぼ同じ。
Rubyの定数は、なんちゃって定数。笑
どういう時に使うの?
CONSTANT = "constant"
のような形でシンプルに代入する時に定数を使う意図としては
enum的な使い方でマスタ情報を model に持っておいて外で呼び出す。(MVCにおいて)
か
そうでなければ、「これ定数だから破壊的メソッドとか、再代入とかしないでよ!」って示す、特別感出す。
ってとこか。
あとがき
本当にこんな違いだけか?って思っているので、
「それ以外にもあるよとか」、「違うよって」とこがあれば伺いたいですorz