Thursday, September 04, 2008

Rubyのメソッドとは

  • 基本的にRubyのメソッドは一種類しかないがオブジェクトが使うメソッドをInstanceメソッドと呼びクラスが使うメソッドをクラスメソッドと呼ぶことがある
  • メソッドはすべてクラスに定義される
  • メソッドは一種類だがそれが定義されるクラスによって呼び名が変わる
  • クラスは4種類ある
  • オブジェクトを生成するクラス、クラスオブジェクトを生成するClassクラス、個々のオブジェクトに対応するSingletonクラス、モジュールである。モジュールはメソッド定義はできるがオブジェクトを生成できないクラスである
  • クラスに定義されたメソッドはそこから生成されるオブジェクトが使いInstanceメソッドと呼ばれる
  • Classクラスに定義されたメソッドはそこから生成されるクラスオブジェクトが使いクラスメソッドと呼ばれる
  • Classクラスも自身により生成されるクラスオブジェクトでありよってClassクラスは自身に定義されたメソッドを使う
  • クラスオブジェクトに対応するSingletonクラスに定義されたメソッドはそのクラスオブジェクトが使いクラスメソッドと呼ばれる
  • モジュールオブジェクトに対応するSingletonクラスに定義されたメソッドはそのモジュールオブジェクトが使いモジュールメソッドと呼ばれる
  • オブジェクトに対応するSingletonクラスに定義されたメソッドはそのオブジェクトが使いSingletonメソッドと呼ばれる
  • Singletonクラスに定義されたメソッドにはシンタックスシュガーがあり、対象オブジェクトでselfをプリペンドしてメソッド定義する
  • メソッドの呼び出しは対象のオブジェクトを指定しておこなう。対象オブジェクトがクラスであるときやモジュールであるときも同様である。呼び出すメソッドが同一のオブジェクト内にある場合つまりレシーバーがselfである場合は、これを省略できる。
  • オブジェクトが利用できるメソッドを調べるメソッドには、Objectクラスに定義されたmethods, public_methods, protected_methods,private_methods,singleton_methodsとModuleクラスに定義されたinstance_methods, public_instance_methods, protected_instance_methods, private_instance_methodsがある
  • メソッドはその可視性を変えることができる。Moduleクラスのメソッドprivate、protected、publicがそれを担う。privateメソッドはレシーバーを指定して呼べない。privateメソッドは継承におけるサブクラスで定義されるメソッド内でも呼べるが、そのクラスから生成されるクラスオブジェクトで定義されるメソッド内では呼べない。そのメソッド呼び出しが特定のオブジェクトをレシーバとすることになるからである。
  • その他にもObject(respond_to?,find_hidden_method,method_added,method,send,public_send,extend) Module(alias_method, instance_method,method_added,method_defined?, method_removed, method_undefined, remove_method,module_function,extend_object,extended)、BasicObject(singleton_method_added, singleton_method_removed,singleton_method_undefined),予約語(alias, undef, defined?)などがある。あとメソッド定義のネストがある。
  • メソッドは継承される。その方法にクラス継承とモジュールMix-inがある
  • クラス継承の方法 superclass, inherited
  • クラスを他のクラスから継承して定義したときはスーパークラスのメソッド定義とそのスーパークラスのクラスメソッド定義がそのままそのクラス(サブクラスという)に引き継がれあたかもそこに定義されたメソッドであるかのように振る舞う
  • スーパークラスに更にスーパークラスがあるときは、それらのメソッド定義も同様にサブクラスにすべて引き継がれる
  • クラスにモジュールをincludeしたときはモジュール内のメソッド定義(つまりInstanceメソッド)のみがそのクラスに引き継がれあたかもそこに定義されたメソッドであるかのように振る舞う。しかしそのモジュールのモジュールメソッド定義は引き継がれない。この点がクラス継承の場合と異なる
  • モジュールに更にモジュールがincludeされていれば、そのメソッド定義も対象のクラスに引き継がれる
  • クラス継承の頂点にはObjectクラス(BasicObjectを一体とする)がありすべてのクラスはこれを黙示的に継承する。さらにObjectクラスはKernelモジュールをincludeしている。従ってクラスから生成されるすべてのオブジェクト(クラスオブジェクト、モジュールオブジェクトを含む)はObject(BasicObjectを含む)のすべてのメソッドとKernelモジュールに定義されたInstanceメソッドを利用できる。この場合レシーバは常にselfとなるのでこれを省略できる。
  • ModuleクラスはObjectクラスを継承しており、更にClassクラスはModuleクラスを継承している。そのためObjectクラスとModuleクラスのすべてのメソッド定義はClassクラスに定義されたメソッドのように振る舞う
  • ここでClassクラスはクラスを生成するクラスだから、すべてのクラスはClassクラスのInstanceメソッド(これにはObjectクラスとModuleクラスのそれが含まれる)をそのクラスメソッドとして利用できる
  • Objectクラスにはオブジェクトの振る舞いを決める基本的なメソッドが定義されている。
  • Moduleクラスには、そこから生成されるモジュールオブジェクトのためのメソッドと、クラスオブジェクトのためのメソッド(ClassクラスはModuleクラスを継承している)がある。もジュールのためのメソッドは、もっぱらpublicメソッドである。なぜならそれをincludeするクラスのオブジェクトがそれらを呼べるようにするためである。一方クラスのためのメソッドは、もっぱらprivateメソッドである。継承クラスでは支障なくそれを呼べるからである。
  • RubyのトップレベルはObjectクラスのインスタンスmainの空間である。ObjectクラスはKernelモジュールをincludeしている。だからKernelモジュールのprivate_instance_methodsはObjectクラスに定義されたメソッドであるかのように振る舞い、トップレベルで呼び出させる。
  • Rubyのトップレベルは、定義に関してはObjectクラスとして働き、実行に関してはそのインスタンスmainとして働く。

No comments: