Object#const_get
クラス名からクラスを得る方法は、リファレンスマニュアルによると eval を使う方法、Object#const_get を使う方法の二通りがあるようです。
#!/usr/local/bin/ruby class Player attr_accessor :name, :age def initialize(name, age) @name = name @age = age end end player1 = Object.const_get('Player').new('rubyo', 19) puts player1.name puts player1.age player2 = eval('Player').new('rubco', 18) puts player2.name puts player2.age
この時クラス名が Net::HTTP のようにネストしている場合の方法についてもマニュアルに解説がありました。
eval で文字列を"コード上のクラス名"として扱うことについては理解できました。一方の const_get は ri すると
------------------------------------------------------- Module#const_get mod.const_get(sym) => obj ------------------------------------------------------------------------ Returns the value of the named constant in _mod_. Math.const_get(:PI) #=> 3.14159265358979
とありました。named 定数の値を取得する。引数はシンボル。この Math の例を見ると特定のモジュール内で定義されている定数を取得できる、という風に見れます。 Math モジュールの中には PI という定数が定義されていて、その値は 3.14159... であり、それを Math モジュールの外から取得する手段として const_get が用意されている、ということでしょう。
- Math モジュールの中の
- PI 定数を取得する
- その値は 3.14159...
モジュールのクラスに相当する Module クラスには constans というメソッドがあり、これで定数一覧を取得できます。
$ irb irb(main):001:0> Math.constants => ["E", "PI"]
と、確かに Math モジュールには PI 定数があることが分かります。
もとい、
Object.const_get('Player') #=> Player
はどう理解すれば良いかというと、先の Math のものをそのまま当てはめると
- Object クラスの中の
- Player 定数を取得する
- その値は Player というクラス名( 'Player' という文字列ではなく、コード上でクラス名と解釈される Player という値)
と言う風になります。ということは Object クラスに Player という定数が定義されていることになるのでしょう。そこで、
#!/usr/local/bin/ruby class Player end Object.constants.each {|const| puts const }
というコードを書き確かめてみました。
$ ruby const_get.rb | grep 'Player' Player
確かに Player という定数が見つかりました。一方、class Player を定義していない段階で const_get してみます。
$ irb irb(main):001:0> Object.const_get(:Player) NameError: uninitialized constant Player from (irb):1:in `const_get' from (irb):1 irb(main):002:0> Object.const_get(:String) => String
組み込みクラスの String では結果が返るのに対して、定義されていないクラスの Player には結果が返りませんでした。
つまり、Object クラスは、そのアプリケーションの中で扱えるクラスのクラス名を定数として持つような機構になっている、と理解しました。