LoginSignup
6
5

More than 1 year has passed since last update.

[Ruby]リフレクションマスターになろう!

Posted at

リフレクションとは?

プログラム実行中に、そのプログラムの情報を取得したり操作したりすること。
デバッグや、正しく定義できてるかの確認など開発をする上で欠かせないものだと思うので、きっちり使えるようにした方が開発スピードは向上します。

オブジェクトについて調べる

オブジェクトが持つインスタンス変数にアクセス

class Foo
  def initialize
    @foo = 1
    @bar = 2
  end
end

foo = Foo.new

# インスタンス変数名の確認
foo.instance_variables #=>[:@foo, :@bar]

# インスタンス変数の存在確認(@は必須)
foo.instance_variable_defined?(:@foo) #=> true

# インスタンス変数の値を参照
foo.instance_variable_get(:@foo) #=> 1

# インスタンス変数の値を更新(存在しない場合は新しく定義)
foo.instance_variable_set(:@foo, 2) #=> 2

オブジェクトが持つメソッドにアクセス

# 親クラスを定義
class ParentClass
  def super_public; end

  private
  def super_private; end

  protected
  def super_protected; end
end

# 子クラスを定義
class ChildClass < ParentClass
  def sub_public; end

  def hello
    puts 'Hello'
  end

  private
  def sub_private; end

  protected
  def sub_protected; end
end

# 特異クラスを定義
def Child.new.singleton; end

child = Cgild.new

# プライベートメソッド以外を取得
child.methods #=> [:singleton, :sub_public, sub_protected, ...]

# パブリックメソッドを取得
child.public_methods #=> [:singleton, :sub_public, ...]

# プライベートメソッドを取得
child.private_methods #=> [:sub_private, :super_private, ...]

# プロテクテッドメソッドを取得
child.protected_methods #=> [:sub_protected, :super_protected]

# 特異メソッドを取得
child.singleton_methods #=> [:singleton]
child.methods(false) #=> [:singleton]

# メソッドが定義されている確認
child.respond_to?(:sub_public) #=> true

# メソッドの呼び出し
child.send(:hello) #=> "Hello"

クラスについて調べる

クラスが持つ値にアクセス

class Foo
  @@foo = 'foo'
  FOO = 'foo'

  def bar
    @@bar = 'bar'
  end
end

# クラス変数を取得する
Foo.class_variables #=> [:@@foo]

# クラス変数が定義されているか確認(@@必須)
Foo.class_variable_defined?(@@foo) #=> true

# クラス変数の値を取得
Foo.class_variable_get(@@foo) #=> "foo"

# クラス変数に値を設定(存在しない場合は新しく作成)
Foo.classvariable_set(@@foo, 'set_foo') #=> "set_foo"

# クラス内に定義されている定数を確認
Foo.constants #=> [:FOO]

# 定数の値を取得する
Foo.const_get(:FOO) #=> "foo"

# 定数に値を設定(存在しない場合は新しく作成)
Foo.const_set(:FOO, 'set_foo') #=> "set_foo"

クラスが持つメソッドにアクセス

# 親クラスを定義
class ParentClass
  def super_public; end

  private
  def super_private; end

  protected
  def super_protected; end
end

# 子クラスを定義
class ChildClass < ParentClass
  def sub_public; end

  def hello
    puts 'Hello'
  end

  private
  def sub_private; end

  protected
  def sub_protected; end
end

# プライベートメソッド以外のインスタンスメソッドを取得
ChildClass.instance_methods #=> [:sub_public, :sub_protected, :super_public, ...]

# パブリックメソッドを取得
ChildClass.public_instance_methods #=> [:sub_public, :super_public, ...]

# プライベートメソッドを取得
ChildClass.private_instance_methods #=> [:sub_private, :super_private, ...]

# プロテクテッドメソッドを取得
ChildClass.protected_instance_methods #=> [:sub_protected, super_protected]

# 指定されたメソッドがプライベートメソッド以外に定義されているか確認
ChildClass.method_defined?(:sub_public) #=> true

# 指定されたメソッドがパブリックメソッドに定義されているか確認
ChildClass.public_method_defined?(:sub_public) #=> true

# 指定されたメソッドがプライベートメソッドに定義されているか確認
ChildClass.private_method_defined?(:sub_private) #=> true

# 指定されたメソッドがプロテクテッドメソッドに定義されているか確認
ChildClass.protected_method_defined?(:sub_protected) #=> true

# クラスの継承構造を参照
ChildClass.ancestors #=> [ChildClass, ParentClass, ...]

# スーパークラスを参照
ChildClass.superclass #=> ParentClass

おわりに

「リフレクション」という聞き慣れない言葉ではあったかと思いますが、内容は結構日頃から似たようなことをしているかと思います。
いろんな操作があるので、必要な情報を取得したり設定できるようにしておきましょう!

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5