せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】Ruby の require はJavaとは違うよ

Rubyのrequire は、
使いたいクラスを宣言する程度の認識しかありませんでした。

Javaのimportと同じ感じだと思っていました。

 
違うのですね。
requireは単にそのファイルを読み込んで実行するだけだから、
平たく言うと何でもできる。
クラスを生成する、という範囲に限られるわけではない。

例えばrequire 'objspace' を実行することによって
ObjectSpace のクラスにメソッドを追加することが出来る


これに気付いたのは、
ObjectSpace#memsize_of を使うときに、require'objspace'するのを知らなくて
NomethodErrorで嵌っていたとき。

JavaだったらそもそもNoClassExceptionになるじゃないですか?
Rubyは違うんだね。
ObjectSpaceってクラス(実体は定数)はすでに定義されているみたいだ。



require前後でメソッド定義状態が変化

p ObjectSpace.methods
require 'objspace'
p ObjectSpace.methods

 
■実行結果

[:each_object, :garbage_collect, :define_finalizer, :undefine_finalizer, :_id2ref, :count_objects, :freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s, :inspect, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :public_constant, :private_constant, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :nil?, :=~, :!~, :eql?, :hash, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
[:each_object, :garbage_collect, :define_finalizer, :undefine_finalizer, :_id2ref, :count_objects, :memsize_of, :memsize_of_all, :count_objects_size, :count_nodes, :count_tdata_objects, :reachable_objects_from, :freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s, :inspect, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :public_constant, :private_constant, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :nil?, :=~, :!~, :eql?, :hash, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]


 

require することでクラスの状態を変える、を自作する

■test.rb

$: << File.dirname(__FILE__)

class Hage
  def self.aaa
  end
end
p Hage.methods.sort
require 'add'
p Hage.methods.sort

 
■add.rb

class Hage
  def self.abb
  end
end



■実行結果

[:!, :!=, :!~, :<, :<=, :<=>, :==, :===, :=~, :>, :>=, :__id__, :__send__, :aaa, :allocate, :ancestors, :autoload, :autoload?, :class, :class_
[:!, :!=, :!~, :<, :<=, :<=>, :==, :===, :=~, :>, :>=, :__id__, :__send__, :aaa, :abb, :allocate, :ancestors, :autoload, :autoload?, :class, :


なるほどね。

 

require しているファイルの実体は?

と調べてみるも、拡張ライブラリであったため中身は分からず。
C:\Ruby200\lib\ruby\2.0.0\i386-mingw32\objspace.so


メタプログラミング。
Rubyらしいなあ。