Rubyメタプログラミング小結

3778 ワード

今日このような質問をされて、以前はいつもこれが比較的に広い概念だと思っていましたが、自分がこれらの特性を使ったことがあっても、これを「メタプログラミング」と呼ぶことを知らなかったので、今日人に聞かれたとき、やっと悟って、それからネット上で自分の平実用的なメタプログラミングとまとめました.
従来のRubyにおけるメタプログラミングとは,実行時に動的に言語構造(クラス,モジュール,インスタンス変数など)を操作できる技術である.再起動せずに、実行時に新しいRubyコードを直接入力して実行することもできます. 
Rubyのメタプログラミングは、「コードを利用してコードを書く」という役割もあります.たとえば、一般的なattr_アクセスなどの方法はそうです.まず私が考えられるのは、自分が使ったことのいくつかです.
1,respond_to?  2,define_method  3,instance_variable_get, instance_variable_set 4,evalでもこの方法はできるだけ避けることができて、実行効率は特に低いです!! 
具体的な意味は、方法の名前を見ると、これらの方法の実現する論理がわかるに違いない.具体的には詳しく見ることができるhttp://api.rubyonrails.org/ソースコードを具体的に分析するのは簡単です.以下は私が他の場所から検索して、今後の仕事の中で自分のプログラミングスキルを高めるのに役立つようにします.1、内省、反射
Rubyでは、実行時にクラスまたはオブジェクトの情報を表示する能力があります.class、instanceを使用できます.methods、  intance_variablesなどの方法で目的を達成します.この技術は内省(Introspection)または反射(Reflection)になると述べた. 
メタプログラムを記述する言語をメタ言語と呼ぶ.操作されるプログラムの言語をターゲット言語と呼ぶ.一つのプログラミング言語は同時に自身のメタ言語である能力を反射あるいは自反と呼ぶ.――ウィキペディアのプログラミング項目から抜粋します.

     
  
classRubyist 
  defwhat_does_he_do 
    @person='A Rubyist' 
    'Ruby programming' 
  end 
end 
   
an_object = Rubyist.new 
puts an_object.class# => Rubyist 
puts an_object.class.instance_methods(false)# => what_does_he_do 
an_object.what_does_he_do 
puts an_object.instance_variables# => @person 

 
 respond_to?方法は反射機構におけるもう一つの有用な方法である.respond_の使用to?方法は、オブジェクトが実行したい情報を処理できるかどうかを事前に知ることができます.すべてのオブジェクトにこのメソッドがあり、respond_を使用します.to?メソッドを使用すると、オブジェクトが指定したメソッドを使用できるかどうかを決定できます.  
 
2,instance_eval Objectクラスにはinstance_という名前のクラスがあります.evalの公開メソッド.このメソッドは、インスタンスによって呼び出され得る.彼はオブジェクトのインスタンス変数を操作する方法を提供した.文字列を使用してパラメータを渡すか、コードブロックを渡すことができます. 
 
  
classRubyist 
  definitialize 
    @geek="Matz" 
  end 
end 
obj = Rubyist.new 
 
# instance_eval obj  
  
obj.instance_evaldo 
  putsself# => #puts@geek# => Matz 
end 
 
 
instanceで_evalが渡すコードブロックは、オブジェクト内で操作できるようにします.オブジェクトの内部で勝手に操作することができ、プライベートなデータはもうありません.instance_evalは、クラスメソッドを追加するためにも使用できます. 

     
  
classRubyist 
end 
   
Rubyist.instance_evaldo 
  defwho 
    "Geek" 
  end 
end 
   
puts Rubyist.who# => Geek 
 
 
const_get, const_set 

似たような、const_getとconst_setは定数を操作するために使用されます.const_getは、指定した定数の値を返します.

     
  
puts Float.const_get(:MIN)# => 2.2250738585072e-308 

const_set指定した定数に指定した値を設定し、そのオブジェクトを返します.定数が存在しない場合は、次のように定数を作成します.

     
  
classRubyist 
end 
puts Rubyist.const_set("PI",22.0/7.0)# => 3.14285714285714 
 
なぜならconst_getは定数の値を返すので、このメソッドを使用してクラスの名前を取得し、このクラスに新しいインスタンス化オブジェクトを追加する方法があります.これにより、実行時にクラスを作成し、インスタンス化することができます. 

     
  
# Let us call our new class 'Rubyist' 
# (we could have prompted the user for a class name) 
class_name ="rubyist".capitalize 
Object.const_set(class_name,Class.new) 
# Let us create a method 'who' 
# (we could have prompted the user for a method name) 
class_name =Object.const_get(class_name) 
puts class_name# => Rubyist 
class_name.class_evaldo 
  define_method:whodo|my_arg| 
    my_arg 
  end 
end 
obj = class_name.new 
puts obj.who('Matz')# => Matz