【一人 Ruby Advent Calendar 2017】文字列から任意のクラスオブジェクトを取得する【2日目】
一人 Ruby Advent Calendar 2017 2日目の記事になります。
今回は "Integer"
みたいな文字列からその名前のクラスオブジェクトを参照する方法を書いてみます。
定義したクラスは誰が保持するのか
Ruby でクラスを定義すると『そのスコープの定数』としてクラスオブジェクトが保持されます。
例えば、下記のように Hoge
クラスのサブクラスとして定義した場合は Hoge
クラスの定数として定義されます。
class Hoge PI = 3.14 class Foo end end p Hoge.constants # => [:PI, :Foo] p Hoge.const_get "Foo" # => Hoge::Foo
なのでサブクラスの場合は Hoge.const_get "クラス名"
のような形でクラスオブジェクトを取得する事ができます。
トップレベルで定義されているクラスオブジェクトを取得する
トップレベルで定義されているクラスは Object
クラスが保持しているので、Object
クラスの定数から取得することができます。
p Object.constants # => [:Binding, :Math, :StringIO, :Integer, :Float, :String, :Array, :Hash, :NilClass, :STDOUT, :STDIN, :NIL, :STDERR, :ARGF, :UncaughtThrowError, :SimpleDelegator, :FileTest, :File, :Delegator, :GC, :Fiber, :FiberError, :Data, :TrueClass, :TRUE, :FalseClass, :FALSE, :Encoding, :ZeroDivisionError, :FloatDomainError, :Numeric, :Rational, :Hoge, :ObjectSpace, :Gem, :DidYouMean, :ENV, :Complex, :Struct, :RegexpError, :Comparable, :Enumerator, :Enumerable, :Regexp, :RUBY_VERSION, :RUBY_RELEASE_DATE, :StopIteration, :RUBY_PLATFORM, :Fixnum, :RubyVM, :Thread, :RUBY_REVISION, :RUBY_DESCRIPTION, :RUBY_PATCHLEVEL, :RUBY_ENGINE, :RUBY_ENGINE_VERSION, :RUBY_COPYRIGHT, :TracePoint, :MatchData, :TOPLEVEL_BINDING, :CROSS_COMPILING, :Bignum, :ARGV, :ThreadGroup, :Dir, :ThreadError, :Mutex, :Queue, :ClosedQueueError, :SizedQueue, :ConditionVariable, :Marshal, :Time, :Range, :IOError, :EOFError, :Process, :Monitor, :IO, :RbConfig, :MonitorMixin, :Random, :Symbol, :Exception, :Signal, :SystemExit, :BasicObject, :Object, :Module, :Class, :Kernel, :Interrupt, :StandardError, :SignalException, :Proc, :IndexError, :TypeError, :ArgumentError, :ScriptError, :KeyError, :RangeError, :NotImplementedError, :SyntaxError, :LoadError, :SystemStackError, :NoMethodError, :Method, :RuntimeError, :SecurityError, :NoMemoryError, :EncodingError, :NameError, :SystemCallError, :UnboundMethod, :Errno, :Warning, :LocalJumpError, :RUBYGEMS_ACTIVATION_MONITOR] p Object.const_get "Integer" # => Integer class Hoge class Foo end end # サブクラスの場合は A::B という風に取得することが出来る p Object.const_get "Hoge::Foo" # => Hoge::Foo
ネストしてるサブクラスも A::B
で取得することができるので便利ですね。