rubyのインスタンスメソッドとクラスメソッド
gold対策。(基礎力確認問題11)
class Cls1 def Cls1.foo puts 'Cls1' end end class Cls2 < Cls1 def foo puts 'Cls2' end end Cls2.foo # >> 'Cls1' Cls2.new.foo # >> Cls2
これ自体は、とてもシンプルですが
gold受験だけでなくruby書く上でも
以下のことを理解しておいた方が良いんじゃないかという気がしてきたので
自分の頭の整理のつもりで書いてみます。
includeでクラスメソッドを追加するには?
moduleにクラスメソッドを記述してclassでincludeしてみる
こんな風に書いてみて、うまくいかない経験は結構あるかと思います。
module M def self.foo puts "M" end end class Cls1 include M end Cls1.foo # ~> -:10:in `<main>': undefined method `foo' for Cls1:Class (NoMethodError)
そこで特異クラスを拡張します
module M def foo puts "M" end end class Cls1 class << self include M end end Cls1.foo # >> M
クラスメソッドってものが、クラスの特異メソッドであることと
特異メソッドの住む場所が、特異クラスであること
が理解できると分かるようになるかと思います。
このあたりは、メタプログラミングRubyが詳しいので割愛します。
extend
extendで同様の実装が可能です。
module M def foo puts "M" end end class Cls1 extend M end Cls1.foo # >> M
ついでにクラスマクロ
ちょっと話がはずれますが
Railsやプラグインのソースコードでよく見る書き方です。
クラスマクロと呼ばれているものです。
attr_accessor()みたいなもんですね。
module M def self.included(base) base.extend(ClassMethods) end module ClassMethods def foo(*args) puts args end end end class Cls1 include M foo :bar, :baz end # >> bar # >> baz