魔術師見習いのノート

プロフィール

魔術師見習い
Author魔術師見習い-_-.
Twitter魔術師見習い

コンピュータ関係のメモを主に書きます.

MENU

メタプログラミングRuby まとめ

投稿日:
タグ:

Ruby

本稿は『メタプログラミングRuby』を読んだ自分用のまとめ。

Rubyの基本メソッド
BasicObject#ancestors
継承関係
メソッドを呼び出す場合,ここで取得する配列の0から順番に検索され,使用される。 例えば,「"hoge".func」のようなメソッドを呼んだ場合,Stringから順に検索される。
[String, Comparable, Object, Kernel, BasicObject]
Kernel#p
オブジェクトの中身を形成(Object#inspectメソッドを呼び出す)して出力する
BasicObject#methods
クラスで定義されたメソッド一覧
public_methods
protected_methods
private_methods
singleton_methods
public・protected・private・特異メソッド一覧
BasicObject#instance_varitables
オブジェクトが持つインスタンス変数一覧
Object#class
クラスを取得
Class#superclass
スーパクラスを取得
オブジェクトモデル
オープンクラス

Rubyでは,定義されたクラスを開いて,内容を変更することができる。

p String.methods.include?(:to_num) # false

class String
  def to_num()
    self.to_i # ※ Rubyのメソッド定義ではreturnがない場合,最後に評価した値を返す
  end
end

a = "123"
p a.to_num # 123

ちなみに既に定義されたメソッドがある場合,上書きする(モンキーパッチ)。

class Hoge
  def func()
    puts "hello"
  end
end

a = Hoge.new

class Hoge
  def func()
    puts "bye"
  end
end

a.func() # byeを出力

Refinements(Ruby2.0以降)
usingを使用すると,引数で指定したモジュールで定義された拡張を現在のクラス、モジュールで有効にできる。
module RefStr
  refine String do
    def to_num()
      self.to_i
    end
  end
end


using RefStr

"123".to_num
メソッド
動的ディスパッチ
Object#send(name [, args, ...])
実行時に呼び出すメソッドを動的に変更する。
class Hoge
  def func1()
    puts "hello"
  end
  def func2(str)
    puts "#{str}"
  end
  def func3()
    puts "bye"
  end
end

a = Hoge.new
a.send(:func1)
a.send(:func2, "yeah!")  
a.send("func3".to_sym)   # 文字列 -> シンボル
動的メソッド
Module#define_method(methodname){|arg, ..| block }
メソッドを動的に定義する。
define_method(:func1){|x| puts x}

class Hoge
  define_method(:func2){|x| puts x}
end

func1("hello")
Hoge.new.func2("bye!")
Object#method_missing(methodname, [*args, &block])
メソッドが見つからない場合,method_missingが呼び出される。
class Hoge
  def method_missing(methodname)
    puts "No #{methodname}!"
  end
end

a = Hoge.new
a.func # No func!
ゴーストメソッド
def method_missing(methodname, *args, &blcok)
  if methodname==:func1 then
    puts "#{args}" 
  else
    super.method_missing(methodname, args, block)
  end
end

func1 1 # [1]
func2 2 # ↓
# NoMethodError: undefined method `func2' for main:Object
#       from (irb):8:in `method_missing'
#       from (irb):13
#       from /usr/bin/irb:12:in `<main>'
その他
可変長引数(*v)
呼び出される側
func(*v)
  p v
end
irb(main):002:0> func(1,2,3)
[1, 2, 3]
=> [1, 2, 3]
呼び出す側
def func(a,b)
   puts "a=#{a}, b=#{b}"
end
irb(main):015:0> args = [1,2].product(["a", "b"])
=> [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]
irb(main):016:0> args.each{|a| func(*a)}
a=1, b=a
a=1, b=b
a=2, b=a
a=2, b=b
=> [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]
irb(main):017:0>

一覧