よくわからなかったのでメモ。環境は Ruby 2.1.5。
以下のようにmixinしたとする。このスクリプトを check_calling_methods.rbとする。
module M def self.included(base) base.extend(ClassMethods) end module ClassMethods def myhello puts 'M, class method, public, hello' end private def myhi puts 'M, class method, private, hi' end end def mybye puts 'M, instance method, public, bye' end private def mychao puts 'M, instance method, private, chao' end end class C include M def myhoo puts 'C, instance method, public, hoo' end def self.myyo puts 'C, class method, public, yo' end private def myjumbo puts 'C, instance method, private, jambo' end class << self private def mymanbo myhello myhi puts 'C, class method, private, manbo' end end end puts "--- public instance method" puts C.instance_methods.grep(/^my/) puts "--- public class method" puts C.singleton_methods.grep(/^my/) puts "--- private instance method" puts C.private_instance_methods.grep(/^my/) puts "--- private class method" puts C.singleton_class.private_instance_methods.grep(/^my/)
クラスメソッド(特異メソッド)とインスタンスメソッドの関係は以下のエントリーを参照のこと。
check_calling_methods.rb を実行すると以下の結果がでる。
% ruby check_calling_methods.rb --- public instance method myhoo mybye --- public class method myyo myhello --- private instance method myjumbo mychao --- private class method mymanbo myhi
myhoo(クラスで定義、public、インスタンスメソッド)で呼び出せる他のメソッド
以下のように書き直すことで他のメソッド(mymanbo, myhi除く)を呼び出せる
def myhoo mybye myjumbo mychao self.class.myyo self.class.myhello puts 'C, instance method, public, hoo' end => M, instance method, public, bye C, instance method, private, jambo M, instance method, private, chao C, class method, public, yo M, class method, public, hello
mymanbo, myhiを呼び出そうとすると以下のようなエラーがでる。
def myhoo self.class.mymanbo puts 'C, instance method, public, hoo' end => check_calling_methods.rb:36:in `myhoo': private method `mymanbo' called for C:Class (NoMethodError) from check_method.rb:72:in `<main>
呼び出せるメソッドは以下のようになっている。
インスタンスメソッド | クラスメソッド | |
public | 呼び出せる | 呼び出せる |
private | 呼び出せる | 呼び出せない |
myhoo(クラスで定義、public、クラスメソッド)で呼び出せる他のメソッド
def self.myyo myhello mymanbo myhi puts 'C, class method, public, yo' end => M, class method, public, hello C, class method, private, manbo M, class method, private, hi C, class method, public, yo
インスタンスメソッドは呼び出せない。よって、呼び出せるメソッドは以下のようになっている。
インスタンスメソッド | クラスメソッド | |
public | 呼び出せない | 呼び出せる |
private | 呼び出せない | 呼び出せる |
おわりに
確実にメタプログラミングの技術を使えば呼び出せるのだろうけどシンプルには上記の結果っぽい。