Rubyメタプログラミング

4432 ワード

  • クラス
  • 方法
  • コードブロック
  • クラスマクロ
  • Evalメソッド
  • インスタンス変数、メソッド、クラス
    インスタンス変数(Instance Variables)は、それらを使用するときに作成されるオブジェクトです.したがって、同じクラスのインスタンスであっても、異なるインスタンス変数を持つことができる.
    技術的には、1つのオブジェクト(インスタンス)は、そのインスタンス変数とその属するクラスの参照を格納するだけです.したがって、1つのオブジェクトのインスタンス変数はオブジェクトにのみ存在し、メソッド(インスタンスメソッド(Instance Methods)と呼ばれる)はオブジェクトが属するクラスに存在します.これは,同じクラスのインスタンスがクラス内のメソッドを共有しているのに,インスタンス変数を共有できない理由である.
    クラス#クラス#
  • クラスもオブジェクトです.
  • クラスもオブジェクトであるため、オブジェクトに適用できるものはすべてクラスに適用できます.クラスは任意のオブジェクトと同様に、独自のクラスがあります.ClassクラスはClassクラスのインスタンスです.
  • 他のオブジェクトと同様に、クラスにもメソッドがあります.オブジェクトのメソッドは、その属するクラスのインスタンスメソッドです.すなわち、クラスのいずれかのメソッドがClassクラスのインスタンスメソッドである.
  • すべてのクラスには共通の祖先Objectクラス(すべてObjectクラスから直接または間接的に継承されている)があり、ObjectクラスはBasicObjectクラス、Rubyクラスの根本から継承されている.
  • クラス名は定数(Constant)です.
  •   n = Class.new
      puts n.ancestors
      puts n.supperclass
      puts n.supperclass.supperclass
      puts n.supperclass.supperclass.supperclass
    

    クラスを開く
    実はこれは方法の再定義と同じ結果ですが、勝手に変更すると深刻な結果をもたらす可能性があります.例えば、あなたが変更したこの方法は他の場所で使用されているので、この方法は慎重に使用してください.この方法が他の結果をもたらさないことを明確にしない限り.
    puts 'abc'.replace('a') # a
    class String
      def replace(string)
        puts '      '
      end
    end
    'abc'.replace('a')  #'      '
    
    を用いてこのプロセスを実現することもできます
    細分化
    module StringExtensions
      refine String do
        def replace(string)
           puts '  '
        end
      end
    end
    

    この方法を使う必要がある場所でusingを使う
    例えば、using StringExtensionsの細分化のメリットは、グローバルな影響を及ぼさないことです.使用する必要がある場所でusingすればいいので、リスクは比較的小さいです.
    呼び出し方法
    クラス内のメソッドはどのように呼び出されますか?
  • メソッドの検索(受信者と祖先チェーン)Rubyでクラス内のメソッドを検索するには、まずそのクラスでこのメソッドを検索し、ない場合は上を検索します.このように類推して、祖先チェーンの先端まで、最後まで、まだ見つからない場合はmethod_を放出します.missing異常.もしJSを知っていたら、あなたはきっとこの過程をよく知っています.JSの中の方法の検索もこの過程に似ているからです.
  • 実行メソッド実行メソッド実行メソッド実行中、Rubyは常に受信者の参照、すなわちself
  • を必要とする.
    selfキーワード
    いつでも、Rubyの中で現在のオブジェクトとして機能するオブジェクトは1つしかなく、このロールとして長く機能するオブジェクトはありません.メソッドを呼び出すと、受信者はselfになります.この瞬間から、すべてのインスタンス変数はselfのインスタンス変数であり、受信者を明確に指定していないすべてのメソッドはself上で呼び出されます.栗を挙げます.
    class Book
      def get_library
        @book_count = 1000
        self
      end
    
      def self.is_my_book?(book)
        false
      end
    end
    b = Book.new
    b.get_library #     ,b    self
    b.is_my_book?('Ruby   ') # undefined method `is_book?' for #<0x00000002b92268> (NoMethodError)
    Book.is_my_book?('Ruby   ') # false
    

    上からis_を呼び出しますmy_book?の方法はどうして間違っていますか?それは,self.is_my_book?(book)Book.is_my_book?(book)に等しいb呼び出し時にselfがbインスタンスオブジェクトを参照し,Bookに等しくないため,メソッドが見つからないエラーを投げ出すからである.
    方法
  • 動的配布(呼び出し方法:オブジェクト.send(メソッド名、パラメータ))
  • class Book
      def create_book
        'Ruby   '  
      end  
      
      def update_book  
        'Ruby   '  
      end  
      
      def delete_book
        'Ruby   '    
      end  
    
      def search_book
        'Ruby   '  
      end
    end  
      
    s = Book.new  
      
    puts s.send(:get_one_name)   
    puts s.send(:get_two_name)  
    puts s.send(:get_three_name) 
    puts s.send(:get_four_name)  
    
  • 動的定義
  • class Book
      ['create', 'update', 'delete', 'search'].each do |item|
        define_method("#{item}_book"){
          puts "#{item}-Ruby   "
        }
      end
    end
    b = Book.new
    b.create_book # create-Ruby   
    b.update_book # update-Ruby   
    b.delete_book # delete-Ruby   
    b.search_book # search-Ruby   
    
  • method_missing(幽霊の方法)
  • # encoding: utf-8
    class Book
      def method_missing(name, *argc)
        if [:create_book, :update_book, :delete_book, :search_book].include?(name)  
          puts "#{name}-Ruby   " 
        else
          super  
        end
      end
    end
    b = Book.new
    b.create_book# create-Ruby   
    b.update_book# update-Ruby   
    b.delete_book # delete-Ruby   
    b.search_book# search-Ruby   
    b.book # undefined method `book'
    

    コードブロック
    ...
    クラスマクロ
    従来の方法では、属性の読み書きを定義するには、次のようなGetメソッドとSetメソッドを各属性に定義する必要があります.
    class Post
      def title=(title)
        @title = title
      end
      def title
        @title
      end
     ....
     ....
    

    文章のようにtitle,content,authorなどの属性を定義すると,3つのグループを書く必要があり,非常に不便である.このとき、Rubyのクラスマクロattr_accessor(moduleのクラスの中の1つのC言語で書く方法、ハイパーリンクを添付して、以上のコードを書くことができます
      class Post
        attr_accessor :title
      end
    

    Evalメソッド