rubyとactive support for expert 2
DESCRIPTION
TRANSCRIPT
Ruby & ActiveSupportfor expart藤岡岳之(xibbar)
Vol.2
このセッションって
xibbarこと藤岡が自分の勉強がてら気づいたことを発表するマニアックなセッションですrubyを詳しくというよりは、Railsのソースを読んでびっくりしたことから派生して、rubyとrailsの仕組みを調べた結果です
今日の内容
1.mix-inをもっと深く2.define_xxxを集めてみたよ3.xxx_evalを集めてみたよ
class methodを定義
# class methodを追加したい
class SampleClass def self.puts_str(str="hello") puts str endend
SampleClass.puts_str
解説ポイント•クラスメソッドとはクラスで共有のメソッド。
mix-inでがんばる
# mix-inでクラスメソッドを追加したい
module SampleModule def self.puts_str(str="hello") puts str endendclass SampleClass include SampleModuleend
SampleClass.puts_str
解説ポイント•ぎゃ!•これでできないのかー。。。•できそうなんだけどなぁ。。
•結論としては、moduleメソッドはSampleModule.puts_strみたいにしか使えない。
% ruby ruby-expert2-2.rbruby-expert2-2.rb:12: undefined method `puts_str' for SampleClass:Class (NoMethodError)
mix-inをもうちょっと
# なんとかmix-inでクラスメソッドを追加したい
module SampleModule def self.included(base) base.extend(ClassMethods) end module ClassMethods def puts_str(str="hello") puts str end endendclass SampleClass include SampleModuleend
SampleClass.puts_str
解説ポイント•なんだこれ?•クラスメソッドを書きたいだけなのに、なげーよ。
•でも、思いついた人はエラい!•includedってなんだ?•extendってなんだ?•上の2つは次で解説
includedとextend
解説ポイント•なんと、includedの引数は呼び出し元そのもの
•extendは引数のモジュールを特異メソッドとして追加
included(class_or_module)
self が include されたときに対象のクラスまたはモジュールを引数にインタプリタから呼び出されます。
module Foo def self.included(mod) p "#{mod} include #{self}" end end class Bar include Foo end # => "Bar include Foo"
extend(module)
引数で指定したモジュールのインスタンスメソッドを self の特異メソッドとして追加します。self を返します。
include は、クラス(のインスタンス)に機能を追加しますが、extend は、ある特定のオブジェクトだけにモジュールの機能を追加したいときに使用します。
module Foo def a 'ok' endend
obj = Object.newobj.extend Foop obj.a #=> "ok"
mix-inでできた
# なんとかmix-inでクラスメソッドを追加したい
module SampleModule def self.included(base) base.extend(ClassMethods) end module ClassMethods def puts_str(str="hello") puts str end endendclass SampleClass include SampleModuleend
SampleClass.puts_str
解説ポイント•includedされたタイミングで呼び出し元にClassMedhodsを特異メソッドとして追加
•以上の結果により、特異メソッドがクラスメソッドのように振る舞う
楽な方法 orzmodule ClassMethods def puts_str(str="hello") puts str endendclass SampleClassend
SampleClass.extend ClassMethodsSampleClass.puts_str
解説ポイント•なんだ、クラスメソッドとしてextend
するだけでよかったのか。•これでincludeをクラスメソッドとしてやってみるとどうなる?
% ruby ruby-expert2-4.rbhello
includeするとどうなるmodule ClassMethods def puts_str(str="hello") puts str endendclass SampleClassend
SampleClass.include ClassMethodsSampleClass.puts_str
解説ポイント•特異メソッドに対する追加はできるけど、全体に対する追加はできない。
•privateなんだとさ。•結論として、extendで特異メソッドの追加はできるが、includeでクラスメソッドの追加をする時は工夫が必要になる。
•こんなところに結論書くなってか。•extendもmix-inの一つだよな。。。
includeしかmix-inと呼ばないなんてことはないよな。。。
% ruby ruby-expert2-5.rbruby-expert2-5.rb:11: private method `include' called for SampleClass:Class (NoMethodError)
とりあえずまとめ
extendでclass methodの追加はできるincludeでclass methodの追加はできないextendで拡張するのもmix-inだ(ろう)
define_xxxを集めてみた
define_method(Moduleクラス)
これ以外にdefine_xxxはなかったorz
気を取り直して使ってみる
class SampleClass define_method(:puts_str){¦str¦ puts str }end
sample=SampleClass.newsample.puts_str("hello")
解説ポイント•まあ無理して使わなくてもいいな•ただ、動的にメソッドを定義できる
•それがカッコいい•inplace editorの受ける部分の定義
% ruby ruby-expert2-6.rbhello
eval兄弟を集めてみた
instance_eval(Objectクラス)class_eval(Moduleクラス)module_eval(Moduleクラス)eval(組み込み関数)
おしまい
おしまい次回以降予定ブロック、クロージャ、イテレータlambda、proc、ついでにbinding継続method_missingerbなんてどう?