rubyオブジェクト

6525 ワード

1.オブジェクトのインスタンス変数は、そのオブジェクトのインスタンスメソッドにのみアクセスできます.インスタンスメソッド以外のコードは、反射メカニズムを除き、インスタンス変数を読み書きできません.
間違った書き方:
#                  ,       self        , initialize   ,  self     Point    。  @x = 0 @y = 0         ,                  Point          ,  initialize    @x     @x          
class Point
  @x = 0
  @y = 0
  def initialize(x, y)
    @x,@y = x,y
  end
end

2.インスタンス属性へのアクセス方法
  • の実現原理は以下の
  • である.
    class Point
      def initialize(x, y)
        @x,@y = x,y
      end
    #      (get)
      def x
        @x
      end
      def y
        @y
      end
    #      (set)
      def x=(value)
        @x = value
      end
      def y=(value)
        @y = value
      end
    end
    #          
    p = Point.new(1,2) 
    q = Point.new(p.x*2,p.y*2) #          ,           
    p.x= 0 #     p.x = 0
    p.y= 2
    
  • このような需要が広大であるため、rubyは自動化する方法を提供し、moduleクラスはattr_を定義した.reader読み取り専用attr_accessorは読み書きするので、上記のコードは
  • に書き換えることができる.
    #        
    class Point
      attr_accessor :x, :y
      def initialize(x, y)
        @x,@y = x,y
      end
    end
    #         
    class Point
      attr_reader :x, :y
      def initialize(x, y)
        @x,@y = x,y
      end
    end
    

    3.オブジェクトを操作するために+-*/を使用する方法
    def +(other)
      raise TypeError,"must Point" unless other.is_a? Point
      Point.new(@x+other.x,@y+other.y)
    end
    def *(scalar)
      Point.new(@x*scalar,@y*scalar)
    end
    
    #      
    p = Point.new(1,2) 
    m = p + 2
    q = p * 2
    #        p*2      ,   2*p       2 integer,  *      Point        ,  p*2  2 * p              coerce   
    def coerce(other)
      [self, other]
    end
    

    []を書き換え、配列とhashにアクセス
    def [](index)
      case index
      when 0, -2: @x      # 0   -2   x
      when 1, -1: @y      # 1   -1   y
      when :x, "x": @x    # :x, "x"   x
      when :y, "y": @y    # :y, "y"   y
      else nil
      end
    end
    

    4.オブジェクトの列挙方法
    def each 
      yield @x
      yield @y
    end
    

    each反復器を定義するとEnumerableモジュールに混入できるいくつかの方法は、eachメソッドに基づいて実装されているためです.
    include Enumerable
    p = Point.new(1,2)
    p.each{|x| p x} # => 1,2
    p.all? {|x| x==0 } #      true   
    

    5.対象の等化をどう判断するか
    def ==(other)
      if other.is_a? Point
        @x == other.x && @y == other.y
      else
        false
      end
    end
    #        .eql?   ==             
    alias eql? ==
    #     eql?      
    def eql? 
      if other.is_a? Point
        @x.eql? other.x && @y.eql? other.y
      else
        false
      end
    end
    #   :             
    # ==         ==
    # eql?   eql?  
    
  • sql? メソッドはハッシュオブジェクトをよく使用するため、単独で定義することはできません.hashメソッドを一緒に定義してオブジェクトのハッシュコード
  • を計算する必要があります.
  • は、2つのオブジェクトの場合である.eql?等しいを返すとhashは等しくなければならずpointを例にhash法
  • を実現する.
    def hash
      code = 17
      code = 37*code + @x.hash
      code = 37*code + @y.hash
    end
    #             (0,1)   (1,0)      hash             ,   point               
    

    6.オブジェクトのソート方法
    include Comparable
    def <==>(other)
      return nil unless other.is_a? Point
      @x**2 + @y**2 <==> other.x**2 + other.y**2 
    end
    

    7.可変クラスの作成方法
    attr_accessor :x, :y
    def add!(other)
      @x += other.x
      @y += other.y
      self 
    end
    

    可変クラスを作成するには、rubyのカーネルクラスであるStructクラスを使用し、他のクラスを生成します.作成時に指定したプロパティには、自動的にアクセサメソッドがあります.
    #       
    Struct.new("Point",:x, :y) # Struct::Point
    Point = Struct.new(:x , :y) #assigns to Point
    #      (                  ,             ,      )
    C = Class.new
    c = C.new
    c.class.to_s # => C
    

    上記のようにコードを書き換えます.
    Point = Struct.new(:x, :y)
    class Point
      def add!(other)
        self.x += other.x
        self.y += other.y
        self
      end
      include Comparable
      def <==>(other)
        return nil unless other.is_a?Point
        self.x**2+self.y**2 <==> other.x**2+other.y**2
      end
    end
    

    structが作成した可変クラスは可変になります
    Point = Struct.new(:x, :y)
    class Point
      undef x= ,y= []=
    end
    

    7.クラスメソッドの追加方法
    class Point
      attr_reader :x, :y
      def Point.sum(*points)
        x, y = 0, 0
        points.each{|point| x+= point.x; y += point.y}
        Point.new(x, y)
      end
      #    self   ,    
      def self.sum(*points)
        x, y = 0, 0
        points.each{|point| x+= point.x; y += point.y}
        Point.new(x, y)
      end
    end
    
  • selfはクラスオブジェクトを表す第1の方法
  • である.
  • 第2の方式は、複数のクラスメソッドを定義する場合に適用され、コードは以下の通りである:
  • #  point      
    class <<  Point
      def sum(*points)
        x, y = 0, 0
        points.each{|point| x+= point.x; y += point.y}
        Point.new(x, y)
      end
      # other class in here
    end
    
    #           
    class Point
    # instance method in there 
      class << self
        # class method in there
      end
    end
    

    8.定数の追加方法
    class Point 
      def initialize(x, y)
        @x, @y = x, y
      end
      ORIGIN = Point.new(0, 0)
    end
    #                ,        initialize          
    #          :
    Point::ORIGIN = Point.new(0, 0)
    

    外部アクセス定数の定義
    Point::ORIGIN
    

    9.クラス変数とクラスインスタンス変数の書き方
    #    
    class Point
      @@n = 0
      @@totalX = 0
      def initialize(x, y)
        @x, @y = x, y
        @@n += 1 
        @@totalX += x
      end
    end
    
    #      
    #                  ,       attr_asscessor         。
    #            ,         ,       ,                            ,              
    class Point
    #    
      def self.new(x, y)
          @n += 1
          @totalX += x
          super
        end
    #    
      class << self
        attr_accessor :n, :totalX
      end
    end
      
    
    #           
    Point.n
    Point.totalX
    

    10.メソッドの可視性~(インスタンス変数クラス変数は効果がプライベートであり、定数が公開されている)
    public:initializeとクラスを除いてデフォルトで定義されたメソッド(これらのメソッドはObjectオブジェクトのプライベートインスタンスメソッドとして定義されています)メソッドはpublic privateです.このクラス(または彼のサブクラス)のインスタンスメソッドにのみ呼び出され、selfによって暗黙的に呼び出され、1つの対象明示的に呼び出されません.mはoの1つの私有の方法で、それではmが呼び出すことしかできなくて、self.m()またはo.m呼び出しprotected:このクラス(または彼のサブクラス)の内部でのみ呼び出され、呼び出しが表示される.正式には、クラスcによって定義されたprotectedメソッドは、oとpがcのサブクラス(またはc自体)である場合にのみ、pのメソッドがo上のメソッドを呼び出すことができる.
    #        
    class Point
    # public methods in here
    protected
    # protected methods in here
    private
    # private methods in here
    end
    
    #                          
    class Widget
    def met_1
    end
    def met_2
    end
    def met_3
    end
    
    protected : met_2
    private :met_1
    end
    

    まとめ:Pointの1つ
    Class Point
      #     
      attr_accessor :x, :y
      # instance method in there 
    
       class << self
        #      
         attr_accessor :count , :totalX
         # class method in there
    
       end
    end
    
    p = Point.new(1,2)
    p.x
    p.y
    Point.count
    Point.totalX