Jak funguje metoda definování [hranaté závorky] v Ruby?

Translate

ProcházímProgramování Ruby - pragmatický průvodce programátorya narazili na tento kus kódu:

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

Nechápu, jak funguje metoda []?

Proč je klíč mimo [], ale když je metoda volána, je uvnitř []?

Může být klíč bez závorek?

Uvědomuji si, že existují mnohem lepší způsoby, jak to napsat, a umím psát vlastní metodu, která funguje, ale tato [] metoda mě jen zmátla ... Jakákoli pomoc je velmi ceněna, díky

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

Všechny odpovědi

Translate

Metody v ruby, na rozdíl od mnoha jazyků, mohou obsahovat některé speciální znaky. Jedním z nich je syntaxe vyhledávání pole.

Pokud byste měli implementovat vlastní třídu hash, kde byste při načítání položky ve vašem hash chtěli obrátit, můžete provést následující:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

Můžete to dokázat voláním hodnoty hash následujícím způsobem:

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

Def [] tedy definoval metodu, která se použije, když to udělátemy_array["key"]Jiné metody, které vám mohou připadat divné, jsou:

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

Pouze pro objasnění, definice a[]metoda nesouvisí s poli nebo hashy. Vezměte si následující (nepřirozený) příklad:

class B
  def []
    "foo"
  end
end

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

Je to jen syntaktický cukr. Existují určité vzory syntaxe, které se překládají do odesílání zpráv. Zejména

a + b

je stejné jako

a.+(b)

a totéž platí pro==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~a!~také.

Taky,

!a

je stejné jako

a.!

a totéž platí pro~.

Pak,

+a

je stejné jako

[email protected]

a totéž platí pro-.

Plus,

a.(b)

je stejné jako

a.call(b)

K dispozici je také speciální syntaxe pro settery:

a.foo = b

je stejné jako

a.foo=(b)

A v neposlední řadě existuje speciální syntaxe pro indexování:

a[b]

je stejné jako

a.[](b)

a

a[b] = c

je stejné jako

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

hranaté závorky jsou jako název metodyArray#sizety mášArray#[]jako metoda a můžete ji dokonce použít jako jakoukoli jinou metodu:

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

poslední je něco jako syntaktický cukr a dělá přesně to samé jako první. TheArray#+pracovat podobně:

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

Můžete dokonce přidat tato čísla:

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

totéž funguje s/, *, -a mnoho dalších.

Zdroj
Translate

Je to přetížitel operátoru, přepíše nebo doplní chování metody uvnitř třídy, kterou jste definovali, nebo třídy, jejíž chování upravujete. Můžete to udělat i jiným operátorům odlišným od []. V tomto případě upravujete chování [], když je voláno v jakékoli instanci třídy SongList.

Pokud máte songlist = SongList.new a pak uděláte songlist ["foobar"], pak bude fungovat vaše vlastní def a bude předpokládat, že "foobar" bude předán jako parametr (klíč) a bude to dělat "foobar" "cokoli, co metoda říká, by mělo být provedeno na klíč."

Snaž se

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
Zdroj
Leave a Reply
You must be logged in to post a answer.
O autorovi