Come funziona la definizione del metodo [parentesi quadra] in Ruby?

Translate

Sto attraversandoProgramming Ruby - una guida pragmatica per programmatorie sono incappato in questo pezzo di codice:

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

Non capisco come funziona la definizione del metodo []?

Perché la chiave è fuori da [], ma quando il metodo viene chiamato, è dentro []?

La chiave può essere senza parentesi?

Mi rendo conto che ci sono modi molto migliori per scrivere questo e so come scrivere il mio metodo che funziona, ma questo [] metodo mi lascia perplesso ... Qualsiasi aiuto è molto apprezzato, grazie

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

Tutte le risposte

Translate

I metodi in ruby, a differenza di molte lingue, possono contenere alcuni caratteri speciali. Uno dei quali è la sintassi di ricerca dell'array.

Se dovessi implementare la tua classe hash in cui durante il recupero di un elemento nel tuo hash, volessi invertirlo, potresti fare quanto segue:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

Puoi dimostrarlo chiamando un hash con quanto segue:

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

Quindi def [] ha definito il metodo che viene utilizzato quando lo faimy_array["key"]Altri metodi che potrebbero sembrarti strani sono:

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

Giusto per chiarire, la definizione di a[]metodo non è correlato ad array o hash. Prendi il seguente esempio (artificioso):

class B
  def []
    "foo"
  end
end

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

È solo zucchero sintattico. Ci sono alcuni modelli di sintassi che vengono tradotti in messaggi inviati. In particolare

a + b

equivale a

a.+(b)

e lo stesso vale per==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~e!~anche.

Anche,

!a

equivale a

a.!

e lo stesso vale per~.

Poi,

+a

equivale a

[email protected]

e lo stesso vale per-.

Più,

a.(b)

equivale a

a.call(b)

C'è anche una sintassi speciale per i setter:

a.foo = b

equivale a

a.foo=(b)

E, ultimo ma non meno importante, esiste una sintassi speciale per l'indicizzazione:

a[b]

equivale a

a.[](b)

e

a[b] = c

equivale a

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

le parentesi quadre sono il nome del metodo comeArray#sizehaiArray#[]come metodo e puoi persino usarlo come qualsiasi altro metodo:

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

l'ultimo è qualcosa come lo zucchero sintattico e fa esattamente la stessa cosa del primo. IlArray#+lavoro simile:

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

Puoi anche aggiungere numeri come questo:

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

lo stesso funziona con/, *, -e molti altri.

fonte
Translate

È un operatore di sovraccarico, sovrascrive o integra il comportamento di un metodo all'interno di una classe che hai definito, o una classe di cui stai modificando il comportamento. Puoi farlo con altri operatori diversi da []. In questo caso stai modificando il comportamento di [] quando viene chiamato su qualsiasi istanza della classe SongList.

Se hai songlist = SongList.new e poi fai songlist ["foobar"] allora la tua definizione personalizzata entrerà in funzione e presumerà che "foobar" debba essere passato come parametro (chiave) e lo farà a "foobar "qualunque cosa dica il metodo dovrebbe essere fatto alla chiave.

Provare

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
fonte
Leave a Reply
You must be logged in to post a answer.
Circa l'autore