メタプログラミング
                Ruby~月曜日~
                  The_haigo




12年11月13日火曜日
こんにちは



12年11月13日火曜日
the_haigoです



12年11月13日火曜日
わたくし実は




12年11月13日火曜日
リア充な草食系男子



12年11月13日火曜日
じゃなかった



12年11月13日火曜日
リア住な僧職系男子
                  なので


12年11月13日火曜日
今回は仏の教え



12年11月13日火曜日
ではなく



12年11月13日火曜日
Matzの教えを布教するため




12年11月13日火曜日
メタプログラミングRubyの

      LT(LongTalk)を行います


12年11月13日火曜日
今回は

               第1章 月曜日:オブジェクトモデル




12年11月13日火曜日
何度も言いますが



12年11月13日火曜日
メタプログラミングとは魔法の
               ようなものであり




12年11月13日火曜日
使い方を誤ると



12年11月13日火曜日
最悪死にます




12年11月13日火曜日
では初めていきます



12年11月13日火曜日
本の流れ
               主に5つの章に別れており

               1章 月曜日∼5章 金曜日でメタプログ
               ラミングを実例を交えながら説明していく

               物語調で書かれており、「レガシーシステ
               ムをハンマーでぶっ叩いて直すやつら」

               という名古屋の怖い人達のような上司ビル
               と学んでいく感じです
12年11月13日火曜日
1.2オープンクラス

               流れ

               Bookwormのソースコードに目を通し

               リファクタリングを行う

               アルファベットとスペースを残して特殊文
               字列を削除する機能が付いている


12年11月13日火曜日
1.2 オープンクラス

          def to_alphanumeric()
           s.gsub /[^wa]/,””
          end
    require ‘test/unit’
    class ToAlphanumericTess < Test::Unit::TestCase
     def test_strips_non_alpanumeric_characters
       assert_equal ‘3 the Magic Number’,
       to_alphanumeric(‘#3, the *Magic, Number*?’)
     end
    end
12年11月13日火曜日
このメソッドはオブジェクト指向じゃないね




               外部のメソッドに文字列を渡すんじゃなく
               て、文字列自身に変換してもらった方がい
               いんじゃないかな?



   ビルさん


12年11月13日火曜日
でもこれって、標準のStringクラスじゃ
               ないですか、メソッド追加するなら、新し
               くAlphaNumericStringクラス作ったほうが
               いいっすよ。でも、そこまでする必要はな
               いかもしれないっすね



                別にStingクラス拡張すればいいじゃん




12年11月13日火曜日
class String
          def to_alphanumeric
             gsub /[^ws]/,’’
          end
       end
        class StringExtensionsTest < Test::Unit::TestCase
           def test_strips_non_alphanumeric_characters
              assert_equal ‘3 the Magic Number’,
             ‘#3, the *Magic, Number*?’.to_alphanumeric
           end
        end

12年11月13日火曜日
Bookworm の関数
          to_alphanumeric
                            オブジェクトモデルは
               ではなく         「このメソッドはどのク
                            ラスのものなのか?」
                            というのがわかるように
    String class            するべき
     def to_alphanumeric




12年11月13日火曜日
1.2.1 クラス定義の中身
               クラスを定義するコードと
               その他のコードの違いはない
     3.times do
                        実行
      class C
         puts “Hello”   Hello
      end               Hello
     end                Hello


     これは同じクラスを3回定義したわけではない

12年11月13日火曜日
class D            obj = D.new
          def x; ‘x’;end    obj.x #=> ‘x’
         end                obj.y #=> ‘y’

         class D
          def y; ’y’; end
         end

          class Dを書いた時はまだ、クラスは存在していない。
          Rubyがクラス定義の中に入った時に、初めて定義をする
          1回目ではxメソッドを定義して2回目の際は既にクラス
          があるので、class Dを再オープンしてyメソッドを追加す
          る。
12年11月13日火曜日
・Rubyのclassキーワードは、クラス宣言と言うより
               も、スコープ演算子のようなものである。
               ・もちろん、存在しないクラスは作成するがそれは副
               作用でしかない
               ・classの主な仕事は、あなたをクラスのコンテキスト
               につれていくことである。




12年11月13日火曜日
既存のクラスを再オープンして、
               いつでもそれを修正できる
                   それが
           オープンクラスだ!(ドヤッ


12年11月13日火曜日
1.2.2オープンクラスの問題点
      def replace(array, from ,to)
        array.each_with_index do |e,i|
           array[i] = to if e == from
        end
      end
      def test_replace
       book_topics = [‘html’,‘java’,‘css’]
       replace(book_topics,‘java’,‘ruby’)
       expected = [‘html’,‘ruby’,‘css’]
       assert_equal expected , book_topics
      end
12年11月13日火曜日
class Array
            def replace(from,to)
               each_with_index do |e,i|
                 self[i] = to if e == from
               end
             end
           end
         def test_replace
          book_topics = [‘html’,‘java’,‘css’]
          replace(book_topics,‘java’,‘ruby’)
          expected = [‘html’,‘ruby’,‘css’]
          assert_equal expected , book_topics
         end
12年11月13日火曜日
バカめ!成功するとでも思ったか!

12年11月13日火曜日
1.2.3 猿マネとモンキーパッチ
           Array.new().methods.grep = /^re/
            #=> [:replace,:reject]


                              つまり
               Arrayに組み込まれている Replaceメソッドを上書きして
                   しまったので、テストコードが失敗した
                          ということである
                   名前衝突がないように気をつけよう!



12年11月13日火曜日
1.3クラスの真実

          class MyClass
           def my_method
             @v = 1
           end
          end

          obj = MyClass.new
          obj.class #=> MyClass



12年11月13日火曜日
インスタンス変数
               obj.instance_variables #=> []
               obj.my_method
               obj.instance_variables #=> [:@v]

         ・Rubyではオブジェクトのインスタンス変数はクラスとも
         何のつながりもない
         ・インスタンス変数は値を代入した時に初めて出現する
         ・同じオブジェクトであってもインスタンス変数の数が異
         なることがある



12年11月13日火曜日
メソッド
     オブジェクト                                     クラス
                          class
               obj                MyClass  
               @var = 1           my_method()

      インスタンス変数                                  メソッド


   ・オブジェクトの内部には、インスタンス変数とクラスへの参照
   があるだけ
   ・クラスにはメソッドがある
   ・クラスを共有しているオブジェクトはメソッドも共有している



12年11月13日火曜日
メソッド
     ・objがmy_method()メソッドを持っているというが
     ・MyClassがmy_method()メソッドを持っているとは言わない
     後者だとMyClassがクラスメソッドとしてmy_method()があると
     勘違いしてしまう

    my_method()をメソッドではなくMyClassのインスタンスメソッ
    ドと呼ぶようにすればよい

          ・オブジェクトに着目している時はメソッド
          ・クラスに着目している時はインスタンスメソッド


12年11月13日火曜日
こんすとらくたー
    class MyClass
     def initialize(hoge,huga)
       @hoge = hoge
       @huga = huga
     end
     attr_accesser :hoge,:huga
    end
     obj = MyClass.new(“りゅか”,”にゃん”)
      obj.instance_variables #=>[:@hoge,:@huga]
      puts obj.hoge + obj.huga #=> “りゅかにゃん”

12年11月13日火曜日
なにやってるか(妄想)
                class MyClass << Class
                   def MyClass.new()
                      initialize(*arg)
                   end
                   def initialize()
                      #何もしない
                  end
                end



12年11月13日火曜日
オープンクラス!
12年11月13日火曜日
class MyClass
                  def initialize(hoge,huga)
                    @hoge = hoge
                    @huga = huga
                  end
                  attr_accesser :hoge,:huga
                 end

                という風にnew()する時に実行される
               initialize()を再定義してインスタンス変数を
                     定義していくんですねー



12年11月13日火曜日
1.3.2 クラス再訪


               クラスは
       オブジェクトである

12年11月13日火曜日
・Classクラス及びすべてのクラスはObjectクラスを
  継承している
  (Classクラスは厳密にはModuleクラスだが)
  ・Objectに当てはまるものはClassにも当てはまる
         String.superclass #=> Object
         Class.class #=> Class
         Class.superclass #=> Module
         Class.instance_methods(false)
         #=> [:superclass,:allocate,:new]


12年11月13日火曜日
Object            Module
               class
       obj1                  superclass            superclass
                                          Class
                        MyClass           new()
                                           ...
       obj2
                class             class

    ・オブジェクトと同じように、クラスも参照を使って保持する
    ・obj1とMyClassはどちらも参照であり違うのは
     ・obj1は変数
     ・MyClassは定数である

12年11月13日火曜日
クラスはオブジェクトで、
 クラス名は定数なのである


12年11月13日火曜日
1.3.3 定数
     ・大文字で始まる参照は、クラス名やモジュール名も含めて全
     て定数である
     ・定数のスコープには、変数のスコープと異なるルールがある

      module MyModule
       MyConstant = ‘外部の定数’
          class MyClass
            MyConstant = ‘内部の定数’
        end
      end           定数はファイルシステムみたいに
                    ツリー状である
12年11月13日火曜日
1.3.4 オブジェクトとクラスまとめ


                  オブジェクトとは何か?

               インスタンス変数の集まりにクラスへのリ
               ンクが付いたものである

               オブジェクトのメソッドは、オブジェクト
               ではなくオブジェクトのクラスに住んでい
               て、クラスのインスタンスメソッドとも呼
               ばれる
12年11月13日火曜日
まとめ2
             クラスとは何か? 

         オブジェクト(Classクラスのインスタンス)に

         ・インスタンスメソッドの一覧

         ・スーパークラスへのリンクがついたものであ
         る

         ClassはModuleのサブクラスであり、クラスもモ
         ジュールである
12年11月13日火曜日
まとめ3

               通常のオブジェクトと同じようにクラスも
               new()などのメソッドを持っている

               これらのメソッドはClassのインスタンスメ
               ソッドである。

               また、クラスにはクラス名という参照を
               使ってアクセスしなければならない

12年11月13日火曜日
1.4 クイズ引かれていない線

               Objectのクラスは?

               Moduleのスーパークラスは?

               Classのクラスは?

               instance_variable_se(“@x”,10)して新しく作っ
               たらどんな感じになる?


12年11月13日火曜日
1.4 クイズ引かれていない線
                                      superclass
     obj1
                 class    Object                   Module
                                        class
                                                            superclass
               class          superclass
     obj2
                                                   Class
                          MyClass                  new()
                                                    ...
   obj3                             class
  @x=10           class                            class


12年11月13日火曜日
1.5メソッドを呼び出す時に何が起きてい
                         るの?

               Rubyはメソッドを呼び出すと以下のことを
               行う

               1メソッドを探す,これをメソッド探索とい
               う

               2メソッドを実行する,これにはselfと呼ばれ
               るものが必要だ

12年11月13日火曜日
心折れたので省略


                                         Object
                                                     発見


                                        MyClass
                                       my_method()

                               class
       obj.my_method()   obj           MySubclass



12年11月13日火曜日
せるふ

               JSとかのthisとかそんなもん 省略したり、
               明示的にメソッド定義できたりします

               カレントオブジェクトっていうんだって!

               クラス定義の中ならクラスがCObj

               関数定義ならインスタンス変数がCObj


12年11月13日火曜日
class Array
                def replace(from,to)
                   each_with_index do |e,i|
                     self[i] = to if e == from
                   end
                 end
               end




12年11月13日火曜日
1.7オブジェクトモデルまとめ
               オブジェクトは複数のインスタンス変数と
               クラスへのリンクで構成されている

               オブジェクトのメソッドはオブジェクトの
               クラスに住んでいる(クラスから見れば、そ
               れはインスタンスメソッドと呼ばれる)

               クラスはClassクラスのオブジェクトであ
               る。クラス名は単なる定数である
12年11月13日火曜日
ClassはModuleのサブクラスである。モ
               ジュールはメソッドを集めたものである。
               クラスはnew()出インスタンス化したり、
               superclass()で階層構造を作ったりできる。

               定数はファイルシステムのようにツリー上
               に配置されている。モジュールやクラスの
               名前がディレクトリ、通常の定数がファイ
               ルのようになっている

12年11月13日火曜日
クラスはそれぞれBasicObjectまで続く継承
               チェーンを持っている

               メソッドを呼び出すと、Ruby はレシーバの
               クラスに向かって一歩右に進み、それから
               継承チェーンを上へ向かって進んでいく。
               メソッドを発見するか継承チェーンが終わ
               るまでそれは続く。

               クラスがモジュールをインクルードする
               と、そのクラスの真上の継承チェーンにモ
               ジュールが挿入される


12年11月13日火曜日
メソッドを呼び出す時、レシーバがselfにな
               る。

               モジュール(あるいはクラス)を定義する
               時、モジュールがselfになる

               インスタンス変数は常にselfのインスタンス
               変数とみなされる

               レシーバを明示的に支持せずにメソッドを
               呼び出すと、selfのメソッドだとみなされる


12年11月13日火曜日

Meta programing ruby monday

  • 1.
    メタプログラミング Ruby~月曜日~ The_haigo 12年11月13日火曜日
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
    リア住な僧職系男子 なので 12年11月13日火曜日
  • 8.
  • 9.
  • 10.
  • 11.
    メタプログラミングRubyの LT(LongTalk)を行います 12年11月13日火曜日
  • 12.
    今回は 第1章 月曜日:オブジェクトモデル 12年11月13日火曜日
  • 13.
  • 14.
    メタプログラミングとは魔法の ようなものであり 12年11月13日火曜日
  • 15.
  • 16.
  • 17.
  • 18.
    本の流れ 主に5つの章に別れており 1章 月曜日∼5章 金曜日でメタプログ ラミングを実例を交えながら説明していく 物語調で書かれており、「レガシーシステ ムをハンマーでぶっ叩いて直すやつら」 という名古屋の怖い人達のような上司ビル と学んでいく感じです 12年11月13日火曜日
  • 19.
    1.2オープンクラス 流れ Bookwormのソースコードに目を通し リファクタリングを行う アルファベットとスペースを残して特殊文 字列を削除する機能が付いている 12年11月13日火曜日
  • 20.
    1.2 オープンクラス def to_alphanumeric() s.gsub /[^wa]/,”” end require ‘test/unit’ class ToAlphanumericTess < Test::Unit::TestCase def test_strips_non_alpanumeric_characters assert_equal ‘3 the Magic Number’, to_alphanumeric(‘#3, the *Magic, Number*?’) end end 12年11月13日火曜日
  • 21.
    このメソッドはオブジェクト指向じゃないね 外部のメソッドに文字列を渡すんじゃなく て、文字列自身に変換してもらった方がい いんじゃないかな? ビルさん 12年11月13日火曜日
  • 22.
    でもこれって、標準のStringクラスじゃ ないですか、メソッド追加するなら、新し くAlphaNumericStringクラス作ったほうが いいっすよ。でも、そこまでする必要はな いかもしれないっすね 別にStingクラス拡張すればいいじゃん 12年11月13日火曜日
  • 23.
    class String def to_alphanumeric gsub /[^ws]/,’’ end end class StringExtensionsTest < Test::Unit::TestCase def test_strips_non_alphanumeric_characters assert_equal ‘3 the Magic Number’, ‘#3, the *Magic, Number*?’.to_alphanumeric end end 12年11月13日火曜日
  • 24.
    Bookworm の関数 to_alphanumeric オブジェクトモデルは ではなく 「このメソッドはどのク ラスのものなのか?」 というのがわかるように String class するべき def to_alphanumeric 12年11月13日火曜日
  • 25.
    1.2.1 クラス定義の中身 クラスを定義するコードと その他のコードの違いはない 3.times do 実行 class C puts “Hello” Hello end Hello end Hello これは同じクラスを3回定義したわけではない 12年11月13日火曜日
  • 26.
    class D obj = D.new def x; ‘x’;end obj.x #=> ‘x’ end obj.y #=> ‘y’ class D def y; ’y’; end end class Dを書いた時はまだ、クラスは存在していない。 Rubyがクラス定義の中に入った時に、初めて定義をする 1回目ではxメソッドを定義して2回目の際は既にクラス があるので、class Dを再オープンしてyメソッドを追加す る。 12年11月13日火曜日
  • 27.
    ・Rubyのclassキーワードは、クラス宣言と言うより も、スコープ演算子のようなものである。 ・もちろん、存在しないクラスは作成するがそれは副 作用でしかない ・classの主な仕事は、あなたをクラスのコンテキスト につれていくことである。 12年11月13日火曜日
  • 28.
    既存のクラスを再オープンして、 いつでもそれを修正できる それが オープンクラスだ!(ドヤッ 12年11月13日火曜日
  • 29.
    1.2.2オープンクラスの問題点 def replace(array, from ,to) array.each_with_index do |e,i| array[i] = to if e == from end end def test_replace book_topics = [‘html’,‘java’,‘css’] replace(book_topics,‘java’,‘ruby’) expected = [‘html’,‘ruby’,‘css’] assert_equal expected , book_topics end 12年11月13日火曜日
  • 30.
    class Array def replace(from,to) each_with_index do |e,i| self[i] = to if e == from end end end def test_replace book_topics = [‘html’,‘java’,‘css’] replace(book_topics,‘java’,‘ruby’) expected = [‘html’,‘ruby’,‘css’] assert_equal expected , book_topics end 12年11月13日火曜日
  • 31.
  • 32.
    1.2.3 猿マネとモンキーパッチ Array.new().methods.grep = /^re/ #=> [:replace,:reject] つまり Arrayに組み込まれている Replaceメソッドを上書きして しまったので、テストコードが失敗した ということである 名前衝突がないように気をつけよう! 12年11月13日火曜日
  • 33.
    1.3クラスの真実 class MyClass def my_method @v = 1 end end obj = MyClass.new obj.class #=> MyClass 12年11月13日火曜日
  • 34.
    インスタンス変数 obj.instance_variables #=> [] obj.my_method obj.instance_variables #=> [:@v] ・Rubyではオブジェクトのインスタンス変数はクラスとも 何のつながりもない ・インスタンス変数は値を代入した時に初めて出現する ・同じオブジェクトであってもインスタンス変数の数が異 なることがある 12年11月13日火曜日
  • 35.
    メソッド オブジェクト クラス class obj     MyClass   @var = 1 my_method() インスタンス変数 メソッド ・オブジェクトの内部には、インスタンス変数とクラスへの参照 があるだけ ・クラスにはメソッドがある ・クラスを共有しているオブジェクトはメソッドも共有している 12年11月13日火曜日
  • 36.
    メソッド ・objがmy_method()メソッドを持っているというが ・MyClassがmy_method()メソッドを持っているとは言わない 後者だとMyClassがクラスメソッドとしてmy_method()があると 勘違いしてしまう my_method()をメソッドではなくMyClassのインスタンスメソッ ドと呼ぶようにすればよい ・オブジェクトに着目している時はメソッド ・クラスに着目している時はインスタンスメソッド 12年11月13日火曜日
  • 37.
    こんすとらくたー class MyClass def initialize(hoge,huga) @hoge = hoge @huga = huga end attr_accesser :hoge,:huga end obj = MyClass.new(“りゅか”,”にゃん”) obj.instance_variables #=>[:@hoge,:@huga] puts obj.hoge + obj.huga #=> “りゅかにゃん” 12年11月13日火曜日
  • 38.
    なにやってるか(妄想) class MyClass << Class def MyClass.new() initialize(*arg) end def initialize() #何もしない end end 12年11月13日火曜日
  • 39.
  • 40.
    class MyClass def initialize(hoge,huga) @hoge = hoge @huga = huga end attr_accesser :hoge,:huga end という風にnew()する時に実行される initialize()を再定義してインスタンス変数を 定義していくんですねー 12年11月13日火曜日
  • 41.
    1.3.2 クラス再訪 クラスは オブジェクトである 12年11月13日火曜日
  • 42.
    ・Classクラス及びすべてのクラスはObjectクラスを 継承している (Classクラスは厳密にはModuleクラスだが) ・Objectに当てはまるものはClassにも当てはまる String.superclass #=> Object Class.class #=> Class Class.superclass #=> Module Class.instance_methods(false) #=> [:superclass,:allocate,:new] 12年11月13日火曜日
  • 43.
    Object Module class obj1 superclass superclass Class MyClass new() ... obj2 class class ・オブジェクトと同じように、クラスも参照を使って保持する ・obj1とMyClassはどちらも参照であり違うのは  ・obj1は変数  ・MyClassは定数である 12年11月13日火曜日
  • 44.
  • 45.
    1.3.3 定数 ・大文字で始まる参照は、クラス名やモジュール名も含めて全 て定数である ・定数のスコープには、変数のスコープと異なるルールがある module MyModule MyConstant = ‘外部の定数’ class MyClass MyConstant = ‘内部の定数’ end end 定数はファイルシステムみたいに ツリー状である 12年11月13日火曜日
  • 46.
    1.3.4 オブジェクトとクラスまとめ    オブジェクトとは何か? インスタンス変数の集まりにクラスへのリ ンクが付いたものである オブジェクトのメソッドは、オブジェクト ではなくオブジェクトのクラスに住んでい て、クラスのインスタンスメソッドとも呼 ばれる 12年11月13日火曜日
  • 47.
    まとめ2     クラスとは何か?  オブジェクト(Classクラスのインスタンス)に ・インスタンスメソッドの一覧 ・スーパークラスへのリンクがついたものであ る ClassはModuleのサブクラスであり、クラスもモ ジュールである 12年11月13日火曜日
  • 48.
    まとめ3 通常のオブジェクトと同じようにクラスも new()などのメソッドを持っている これらのメソッドはClassのインスタンスメ ソッドである。 また、クラスにはクラス名という参照を 使ってアクセスしなければならない 12年11月13日火曜日
  • 49.
    1.4 クイズ引かれていない線 Objectのクラスは? Moduleのスーパークラスは? Classのクラスは? instance_variable_se(“@x”,10)して新しく作っ たらどんな感じになる? 12年11月13日火曜日
  • 50.
    1.4 クイズ引かれていない線 superclass obj1 class Object Module class superclass class superclass obj2 Class MyClass new() ... obj3 class @x=10 class class 12年11月13日火曜日
  • 51.
    1.5メソッドを呼び出す時に何が起きてい るの? Rubyはメソッドを呼び出すと以下のことを 行う 1メソッドを探す,これをメソッド探索とい う 2メソッドを実行する,これにはselfと呼ばれ るものが必要だ 12年11月13日火曜日
  • 52.
    心折れたので省略 Object 発見 MyClass my_method() class obj.my_method() obj MySubclass 12年11月13日火曜日
  • 53.
    せるふ JSとかのthisとかそんなもん 省略したり、 明示的にメソッド定義できたりします カレントオブジェクトっていうんだって! クラス定義の中ならクラスがCObj 関数定義ならインスタンス変数がCObj 12年11月13日火曜日
  • 54.
    class Array def replace(from,to) each_with_index do |e,i| self[i] = to if e == from end end end 12年11月13日火曜日
  • 55.
    1.7オブジェクトモデルまとめ オブジェクトは複数のインスタンス変数と クラスへのリンクで構成されている オブジェクトのメソッドはオブジェクトの クラスに住んでいる(クラスから見れば、そ れはインスタンスメソッドと呼ばれる) クラスはClassクラスのオブジェクトであ る。クラス名は単なる定数である 12年11月13日火曜日
  • 56.
    ClassはModuleのサブクラスである。モ ジュールはメソッドを集めたものである。 クラスはnew()出インスタンス化したり、 superclass()で階層構造を作ったりできる。 定数はファイルシステムのようにツリー上 に配置されている。モジュールやクラスの 名前がディレクトリ、通常の定数がファイ ルのようになっている 12年11月13日火曜日
  • 57.
    クラスはそれぞれBasicObjectまで続く継承 チェーンを持っている メソッドを呼び出すと、Ruby はレシーバの クラスに向かって一歩右に進み、それから 継承チェーンを上へ向かって進んでいく。 メソッドを発見するか継承チェーンが終わ るまでそれは続く。 クラスがモジュールをインクルードする と、そのクラスの真上の継承チェーンにモ ジュールが挿入される 12年11月13日火曜日
  • 58.
    メソッドを呼び出す時、レシーバがselfにな る。 モジュール(あるいはクラス)を定義する 時、モジュールがselfになる インスタンス変数は常にselfのインスタンス 変数とみなされる レシーバを明示的に支持せずにメソッドを 呼び出すと、selfのメソッドだとみなされる 12年11月13日火曜日