Comment fonctionne la définition de la méthode [crochet] dans Ruby?

Translate

Je traverseProgrammation Ruby - un guide pragmatique pour les programmeurset sont tombés sur ce morceau de code:

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

Je ne comprends pas comment la méthode de définition [] fonctionne?

Pourquoi la clé est-elle en dehors de [], mais lorsque la méthode est appelée, elle se trouve à l'intérieur de []?

La clé peut-elle être sans parenthèse?

Je me rends compte qu'il existe de bien meilleures façons d'écrire ceci, et je sais comment écrire ma propre méthode qui fonctionne, mais cette méthode [] me déroute ... Toute aide est grandement appréciée, merci

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

Toutes les réponses

Translate

Les méthodes en ruby, contrairement à de nombreuses langues, peuvent contenir des caractères spéciaux. L'une d'elles est la syntaxe de recherche de tableau.

Si vous deviez implémenter votre propre classe de hachage où, lors de la récupération d'un élément de votre hachage, vous vouliez l'inverser, vous pouvez effectuer les opérations suivantes:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

Vous pouvez le prouver en appelant un hachage avec ce qui suit:

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

Ainsi, le def [] a défini la méthode qui est utilisée lorsque vous faitesmy_array["key"]D'autres méthodes qui peuvent vous sembler étranges sont:

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

Juste pour clarifier, la définition d'un[]n'est pas liée aux tableaux ou aux hachages. Prenons l'exemple suivant (artificiel):

class B
  def []
    "foo"
  end
end

 B.new[]
 => "foo" 
La source
Translate

C'est juste du sucre syntaxique. Il existe certains modèles de syntaxe qui sont traduits en envois de messages. En particulier

a + b

est le même que

a.+(b)

et il en va de même pour==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~et!~ainsi que.

Également,

!a

est le même que

a.!

et il en va de même pour~.

Ensuite,

+a

est le même que

[email protected]

et il en va de même pour-.

Plus,

a.(b)

est le même que

a.call(b)

Il existe également une syntaxe spéciale pour les setters:

a.foo = b

est le même que

a.foo=(b)

Enfin, il existe une syntaxe spéciale pour l'indexation:

a[b]

est le même que

a.[](b)

et

a[b] = c

est le même que

a.[]=(b, c)
La source
Translate

les crochets sont le nom de la méthode commeArray#sizevous avezArray#[]comme méthode et vous pouvez même l'utiliser comme n'importe quelle autre méthode:

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

le dernier est quelque chose comme le sucre syntaxique et fait exactement la même chose que le premier. leArray#+travail similaire:

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

Vous pouvez même ajouter des nombres comme celui-ci:

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

la même chose fonctionne avec/, *, -et beaucoup plus.

La source
Translate

C'est un surchargeur d'opérateurs, il remplace ou complète le comportement d'une méthode à l'intérieur d'une classe que vous avez définie, ou d'une classe dont vous modifiez le comportement. Vous pouvez le faire à d'autres opérateurs différents de []. Dans ce cas, vous modifiez le comportement de [] lorsqu'il est appelé sur une instance de la classe SongList.

Si vous avez songlist = SongList.new et que vous faites songlist ["foobar"] alors votre définition personnalisée entrera en vigueur et supposera que "foobar" doit être passé comme paramètre (clé) et il le fera pour "foobar "tout ce que la méthode dit doit être fait pour la clé.

Essayer

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
La source
Leave a Reply
You must be logged in to post a answer.
A propos de l'auteur