Jak działa metoda definiowania [nawiasu kwadratowego] w Ruby?

Translate

PrzechodzęProgramowanie Ruby - pragmatyczny przewodnik dla programistówi natknąłem się na ten fragment kodu:

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

Nie rozumiem, jak działa metoda definiowania []?

Dlaczego klucz znajduje się na zewnątrz [], ale gdy wywoływana jest metoda, znajduje się wewnątrz []?

Czy klucz może być bez nawiasów?

Zdaję sobie sprawę, że są o wiele lepsze sposoby, aby to napisać, i wiem, jak napisać własną metodę, która działa, ale ta [] metoda po prostu mnie wprawia w zakłopotanie ... Każda pomoc jest bardzo doceniana, dzięki

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

Wszystkie odpowiedzi

Translate

Metody w języku ruby, w przeciwieństwie do wielu języków, mogą zawierać znaki specjalne. Jednym z nich jest składnia wyszukiwania tablic.

Gdybyś miał zaimplementować własną klasę skrótu, w której podczas pobierania elementu z twojego skrótu chciałbyś go cofnąć, możesz wykonać następujące czynności:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

Możesz to udowodnić, wywołując skrót z następującymi elementami:

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

Zatem def [] zdefiniował metodę, która jest używana, gdy to robiszmy_array["key"]Inne metody, które mogą wyglądać dziwnie, to:

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

Dla wyjaśnienia, definicja a[]metoda nie jest związana z tablicami ani skrótami. Weźmy następujący (wymyślony) przykład:

class B
  def []
    "foo"
  end
end

 B.new[]
 => "foo" 
Źródło
Translate

To tylko cukier syntaktyczny. Istnieją pewne wzorce składni, które są tłumaczone na wysyłanie wiadomości. W szczególności

a + b

jest taki sam jak

a.+(b)

i to samo dotyczy==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~i!~także.

Również,

!a

jest taki sam jak

a.!

i to samo dotyczy~.

Następnie,

+a

jest taki sam jak

[email protected]

i to samo dotyczy-.

Plus,

a.(b)

jest taki sam jak

a.call(b)

Istnieje również specjalna składnia dla ustawiaczy:

a.foo = b

jest taki sam jak

a.foo=(b)

I wreszcie, istnieje specjalna składnia indeksowania:

a[b]

jest taki sam jak

a.[](b)

i

a[b] = c

jest taki sam jak

a.[]=(b, c)
Źródło
Translate

nawiasy kwadratowe to nazwa metodyArray#sizety maszArray#[]jako metodę i możesz jej nawet używać jak każdej innej metody:

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

ostatni jest czymś w rodzaju cukru syntaktycznego i robi dokładnie to samo, co pierwszy. PlikArray#+działają podobnie:

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

Możesz nawet dodać takie liczby:

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

to samo działa z/, *, -i wiele więcej.

Źródło
Translate

Jest to narzędzie do przeciążania operatorów, nadpisuje lub uzupełnia zachowanie metody wewnątrz zdefiniowanej przez Ciebie klasy lub klasy, której zachowanie modyfikujesz. Możesz to zrobić z innymi operatorami innymi niż []. W tym przypadku modyfikujesz zachowanie elementu [], gdy jest on wywoływany w dowolnej instancji klasy SongList.

Jeśli masz songlist = SongList.new, a następnie wykonasz songlist ["foobar"], wtedy twoja niestandardowa definicja zacznie działać i przyjmie, że "foobar" ma być przekazane jako parametr (klucz) i zrobi to do "foobar" „cokolwiek mówi metoda, należy zrobić klucz.

Próbować

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
Źródło
Leave a Reply
You must be logged in to post a answer.
O autorze