Como funciona o método de [colchete] no Ruby?

Translate

Estou passandoProgramando Ruby - um guia pragmático para programadorese descobri este trecho de código:

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

Eu não entendo como funciona a definição de [] método?

Por que a chave está fora de [], mas quando o método é chamado, está dentro de []?

A chave pode estar sem parênteses?

Sei que há maneiras muito melhores de escrever isso, e sei como escrever meu próprio método que funcione, mas esse [] método me deixa perplexo ... Qualquer ajuda é muito apreciada, obrigado

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

Todas as respostas

Translate

Os métodos em ruby, ao contrário de muitos idiomas, podem conter alguns caracteres especiais. Uma delas é a sintaxe de pesquisa de array.

Se você fosse implementar sua própria classe de hash em que, ao recuperar um item em seu hash, você desejasse revertê-lo, você poderia fazer o seguinte:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

Você pode provar isso chamando um hash com o seguinte:

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

Portanto, o def [] definiu o método que é usado quando você fazmy_array["key"]Outros métodos que podem parecer estranhos para você são:

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

Só para esclarecer, a definição de um[]método não está relacionado a matrizes ou hashes. Veja o seguinte exemplo (inventado):

class B
  def []
    "foo"
  end
end

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

É apenas açúcar sintático. Existem certos padrões de sintaxe que são traduzidos em envio de mensagens. Em particular

a + b

é o mesmo que

a.+(b)

e o mesmo se aplica a==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~e!~também.

Além disso,

!a

é o mesmo que

a.!

e o mesmo se aplica a~.

Então,

+a

é o mesmo que

[email protected]

e o mesmo se aplica a-.

Mais,

a.(b)

é o mesmo que

a.call(b)

Também existe uma sintaxe especial para setters:

a.foo = b

é o mesmo que

a.foo=(b)

E por último, mas não menos importante, existe uma sintaxe especial para indexação:

a[b]

é o mesmo que

a.[](b)

e

a[b] = c

é o mesmo que

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

os colchetes são o nome do método comoArray#sizeVocê temArray#[]como um método e você pode até mesmo usá-lo como qualquer outro método:

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

o último é algo como açúcar sintático e faz exatamente o mesmo que o primeiro. oArray#+trabalho semelhante:

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

Você pode até adicionar números como este:

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

o mesmo funciona com/, *, -e muitos mais.

Fonte
Translate

É um sobrecarregador de operadores, que substitui ou complementa o comportamento de um método dentro de uma classe que você definiu ou de uma classe cujo comportamento você está modificando. Você pode fazer isso com outros operadores diferentes de []. Nesse caso, você está modificando o comportamento de [] quando ele é chamado em qualquer instância da classe SongList.

Se você tem songlist = SongList.new e então faz songlist ["foobar"] então seu padrão personalizado entrará em operação e assumirá que "foobar" deve ser passado como parâmetro (chave) e servirá para "foobar "tudo o que o método diz deve ser feito com a chave.

Experimentar

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.
Sobre o autor