クラスメソッドの定義方法いろいろ
class Test
def Test.foo
'クラスメソッドfoo'
end
end
class Test
def self.foo
'クラスメソッドfoo'
end
end
class Test
class << self
def foo
'クラスメソッドfoo'
end
end
end
class Test
end
class << Test
def foo
'クラスメソッドfoo'
end
end
module Bar
def foo
'クラスメソッドfoo'
end
end
class Test
extend(Bar)
end
- 書き方はいろいろあるが、すべて、同じクラスメソッドfooを追加していることになる。実行すると以下の結果になる。
Test.foo
=> "クラスメソッドfoo"
includeとextend
- includeはモジュールをインスタンスメソッドとして追加する。
- extendはモジュールをクラスメソッドとして追加する。*1
module Bar
def foo
'メソッドfoo'
end
end
class Test
extend Bar
end
Test.foo
=> "メソッドfoo"
class Test2
include Bar
end
Test2.foo
NoMethodError: undefined method 'foo' for Test2:Class
Test2.new.foo
=> "メソッドfoo"
module Bar
def self.append_features(base)
super
base.extend(ClassMethods)
end
module ClassMethods
def foo
'クラスメソッドfoo'
end
end
end
class Test
include Bar
end
Test.foo
=> "クラスメソッドfoo"
define_method
- メソッドの中で動的にメソッドを定義する。(メソッドを定義するメソッドを作る。例えば、auto_complete_for :bank, :nameのauto_complete_forは、auto_complete_for_bank_nameというメソッドを追加するメソッドと言える。)
module Bar
def self.append_features(base)
super
base.extend(ClassMethods)
end
module ClassMethods
def make_foo
define_method('foo') do
'クラスメソッドfoo'
end
end
end
end
class Test
include Bar
end
Test.new.foo
NoMethodError: undefined method 'foo' for
Test.make_foo
Test.new.foo
=> "クラスメソッドfoo"
procとlambda
- コードブロックをオブジェクトとして取り扱う場合に利用。
code = proc {puts 'オブジェクト化されたコードブロック'}
code.call
オブジェクト化されたコードブロック
code2 = Proc.new {puts 'オブジェクト化されたコードブロック2'}
code3 = lambda {puts 'オブジェクト化されたコードブロック3'}
code2.call
オブジェクト化されたコードブロック2
code3.call
オブジェクト化されたコードブロック3
- コードブロックを受け取るメソッドの定義方法いろいろ
def foo
a = Proc.new
a.call('コードブロックを受け取って実行する')
end
foo {|s| puts s}
コードブロックを受け取って実行する
def foo2
proc.call('コードブロックを受け取って実行する2')
end
def foo3
lambda.call('コードブロックを受け取って実行する3')
end
def foo4(&p)
p.call('コードブロックを受け取って実行する4')
end
def foo5
yield('コードブロックを受け取って実行する5')
end
foo2 {|s| puts s}
コードブロックを受け取って実行する2
foo3 {|s| puts s}
コードブロックを受け取って実行する3
foo4 {|s| puts s}
コードブロックを受け取って実行する4
foo5 {|s| puts s}
コードブロックを受け取って実行する5