Wie funktioniert die Definition der [eckigen Klammer] in Ruby?

Translate

Ich gehe durchProgrammieren von Ruby - eine pragmatische Programmieranleitungund sind über diesen Code gestolpert:

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

Ich verstehe nicht, wie die Definition der [] -Methode funktioniert.

Warum befindet sich der Schlüssel außerhalb von [], aber wenn die Methode aufgerufen wird, befindet er sich innerhalb von []?

Kann der Schlüssel ohne Klammern sein?

Mir ist klar, dass es weitaus bessere Möglichkeiten gibt, dies zu schreiben, und ich weiß, wie ich meine eigene Methode schreibe, die funktioniert, aber diese [] Methode verwirrt mich nur ... Jede Hilfe wird sehr geschätzt, danke

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

Alle Antworten

Translate

Methoden in Ruby können im Gegensatz zu vielen Sprachen einige Sonderzeichen enthalten. Eine davon ist die Array-Lookup-Syntax.

Wenn Sie Ihre eigene Hash-Klasse implementieren, in der Sie beim Abrufen eines Elements in Ihrem Hash Folgendes rückgängig machen möchten, können Sie Folgendes tun:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

Sie können dies beweisen, indem Sie einen Hash wie folgt aufrufen:

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

Das def [] hat also die Methode definiert, die verwendet wird, wenn Sie dies tunmy_array["key"]Andere Methoden, die für Sie seltsam aussehen können, sind:

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

Nur um zu verdeutlichen, die Definition von a[]Methode ist nicht mit Arrays oder Hashes verbunden. Nehmen Sie das folgende (erfundene) Beispiel:

class B
  def []
    "foo"
  end
end

 B.new[]
 => "foo" 
Quelle
Translate

Es ist nur syntaktischer Zucker. Es gibt bestimmte Syntaxmuster, die in Nachrichtensendungen übersetzt werden. Speziell

a + b

ist das gleiche wie

a.+(b)

und das gleiche gilt für==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~und!~auch.

Ebenfalls,

!a

ist das gleiche wie

a.!

und das gleiche gilt für~.

Dann,

+a

ist das gleiche wie

[email protected]

und das gleiche gilt für-.

Plus,

a.(b)

ist das gleiche wie

a.call(b)

Es gibt auch eine spezielle Syntax für Setter:

a.foo = b

ist das gleiche wie

a.foo=(b)

Und zu guter Letzt gibt es eine spezielle Syntax für die Indizierung:

a[b]

ist das gleiche wie

a.[](b)

und

a[b] = c

ist das gleiche wie

a.[]=(b, c)
Quelle
Translate

Die eckigen Klammern sind wie der MethodennameArray#sizedu hastArray#[]als Methode und Sie können es sogar wie jede andere Methode verwenden:

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

Der letzte ist so etwas wie syntaktischer Zucker und macht genau das gleiche wie der erste. DasArray#+Arbeit ähnlich:

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

Sie können sogar Zahlen wie diese hinzufügen:

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

das gleiche funktioniert mit/, *, -und viele mehr.

Quelle
Translate

Es ist ein Operator-Overlader, der das Verhalten einer Methode innerhalb einer von Ihnen definierten Klasse oder einer Klasse, deren Verhalten Sie ändern, überschreibt oder ergänzt. Sie können dies auch für andere Operatoren als [] tun. In diesem Fall ändern Sie das Verhalten von [], wenn es für Instanzen der Klasse SongList aufgerufen wird.

Wenn Sie songlist = SongList.new haben und dann songlist ["foobar"] ausführen, wird Ihre benutzerdefinierte Definition in Betrieb genommen und es wird davon ausgegangen, dass "foobar" als Parameter (Schlüssel) übergeben werden soll und "foobar" "Was auch immer die Methode sagt, sollte zum Schlüssel gemacht werden.

Versuchen

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
Quelle
Leave a Reply
You must be logged in to post a answer.
Über den Autor