Rubyでの[角かっこ]メソッドの定義はどのように機能しますか?

Translate

私は通過していますRubyのプログラミング-実用的なプログラマーガイドそして、このコードに出くわしました:

class SongList
  def [](key)
    if key.kind_of?(Integer)
      return @songs[key]
    else
      for i in [email protected]
        return @songs[i] if key == @songs[i].name
      end
    end
    return nil
  end
end

[]メソッドの定義がどのように機能するのかわかりませんか?

キーが[]の外側にあるのに、メソッドが呼び出されたときに[]の内側にあるのはなぜですか?

キーを括弧なしにすることはできますか?

これを書くにははるかに良い方法があることを理解し、機能する独自のメソッドを書く方法を知っていますが、この[]メソッドは私を困惑させます...どんな助けでも大歓迎です、ありがとう

This question and all comments follow the "Attribution Required."

すべての答え

Translate

多くの言語とは異なり、Rubyのメソッドにはいくつかの特殊文字を含めることができます。その1つが配列ルックアップ構文です。

ハッシュ内のアイテムを取得するときにそれを逆にしたい独自のハッシュクラスを実装する場合は、次のようにすることができます。

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

次のようにハッシュを呼び出すことで、これを証明できます。

a = {:foo => "bar"}
 => {:foo=>"bar"} 
a.[](:foo)
 => "bar" 
a.send(:[], :foo)
 => "bar" 

したがって、def []は、実行時に使用されるメソッドを定義しました。my_array["key"]あなたにとって奇妙に見えるかもしれない他の方法は次のとおりです。

class SillyHash < Hash

  def [](key)
    super.reverse
  end

  def []=(key, value)
    #do something
  end

  def some_value=(value)
    #do something
  end

  def is_valid?(value)
    #some boolean expression
  end

end

明確にするために、の定義[]メソッドは配列やハッシュとは無関係です。次の(考案された)例を見てください。

class B
  def []
    "foo"
  end
end

 B.new[]
 => "foo" 
ソース
Translate

それは単なる構文糖衣です。メッセージ送信に変換される特定の構文パターンがあります。特に

a + b

と同じです

a.+(b)

同じことが当てはまります==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~そして!~同様に。

また、

!a

と同じです

a.!

同じことが当てはまります~.

次に、

+a

と同じです

[email protected]

同じことが当てはまります-.

プラス、

a.(b)

と同じです

a.call(b)

セッターには特別な構文もあります。

a.foo = b

と同じです

a.foo=(b)

最後になりましたが、インデックス作成には特別な構文があります。

a[b]

と同じです

a.[](b)

そして

a[b] = c

と同じです

a.[]=(b, c)
ソース
Translate

角括弧は次のようなメソッド名ですArray#sizeあなたが持っているArray#[]メソッドとして、他のメソッドと同じように使用することもできます。

array = [ 'a', 'b', 'c']
array.[](0) #=> 'a'
array.[] 1  #=> 'b'
array[2]    #=> 'c'

最後のものはシンタックスシュガーのようなもので、最初のものとまったく同じです。ザ・Array#+同様に動作します:

array1 = [ 'a', 'b' ]
array2 = [ 'c', 'd' ]
array1.+(array2) #=> [ 'a', 'b', 'c', 'd' ]
array1.+ array2  #=> [ 'a', 'b', 'c', 'd' ]
array1 + array2  #=> [ 'a', 'b', 'c', 'd' ]

次のような番号を追加することもできます。

1.+(1) #=> 2
1.+ 1  #=> 2
1 + 1  #=> 2

同じことが動作します/, *, -などなど。

ソース
Translate

これは演算子オーバーロードであり、定義したクラス内のメソッドの動作、または動作を変更するクラスをオーバーライドまたは補足します。 []とは異なる他の演算子に対しても実行できます。この場合、クラスSongListのインスタンスで呼び出されたときの[]の動作を変更しています。

songlist = SongList.newがあり、songlist ["foobar"]を実行すると、カスタムdefが動作し、 "foobar"がパラメーター(キー)として渡されると想定し、 "foobar"に対して実行されます。 「メソッドが言うことは何でもキーに対して行われるべきです。

試してみてください

class Overruler
    def [] (input)
          if input.instance_of?(String)
            puts "string"
          else
            puts "not string"
          end
     end
end
foo = Overruler.new
foo["bar"].inspect
foo[1].inspect
ソース
Leave a Reply
You must be logged in to post a answer.
著者について