如何在Ruby中定义[方括号]方法?

时间:2022-07-17 19:04:15

I am going through Programming Ruby - a pragmatic programmers guide and have stumbled on this piece of code:

我正在进行Ruby编程——一个实用的程序员指南,无意中发现了这段代码:

class SongList
  def [](key)
    if key.kind_of?(Integer)
      return @songs[key]
    else
      for i in 0...@songs.length
        return @songs[i] if key == @songs[i].name
      end
    end
    return nil
  end
end

I do not understand how defining [ ] method works?

我不明白定义[]方法是如何工作的?

Why is the key outside the [ ], but when the method is called, it is inside [ ]?

为什么键在[]之外,但当方法被调用时,它在[]内部?

Can key be without parenthesis?

键可以没有括号吗?

I realize there are far better ways to write this, and know how to write my own method that works, but this [ ] method just baffles me... Any help is greatly appreciated, thanks

我知道有很多更好的方法可以写这个,也知道如何写我自己的方法,但是这个方法让我很困惑……非常感谢您的帮助,谢谢

4 个解决方案

#1


36  

Methods in ruby, unlike many languages can contain some special characters. One of which is the array lookup syntax.

与许多语言不同,ruby中的方法可以包含一些特殊字符。其中之一是数组查找语法。

If you were to implement your own hash class where when retrieving an item in your hash, you wanted to reverse it, you could do the following:

如果你要实现你自己的哈希类,当你在哈希中检索一个条目时,你想要反向它,你可以做以下事情:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

You can prove this by calling a hash with the following:

可以通过调用散列来证明这一点:

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

So the def [] defined the method that is used when you do my_array["key"] Other methods that may look strange to you are:

因此,def[]定义了在执行my_array["key"]时使用的方法,其他可能看起来很奇怪的方法是:

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

Just to clarify, the definition of a [] method is unrelated to arrays or hashes. Take the following (contrived) example:

澄清一下,[]方法的定义与数组或散列无关。以下列(人为的)例子为例:

class B
  def []
    "foo"
  end
end

 B.new[]
 => "foo" 

#2


39  

It's just syntactic sugar. There are certain syntax patterns that get translated into message sends. In particular

只是语法糖。有一些语法模式被翻译成消息发送。特别是

a + b

is the same as

是一样的

a.+(b)

and the same applies to ==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~ and !~ as well.

同样适用于= =、! =、<、>、< =、> =、< = >、= = = &、|,*,/,,%,* *,> >,< <,! = =,= ~ ! ~。

Also,

同时,

!a

is the same as

是一样的

a.!

and the same applies to ~.

这同样适用于~。

Then,

然后,

+a

is the same as

是一样的

a.+@

and the same applies to -.

这同样适用于-。

Plus,

另外,

a.(b)

is the same as

是一样的

a.call(b)

There is also special syntax for setters:

设置程序也有特殊的语法:

a.foo = b

is the same as

是一样的

a.foo=(b)

And last but not least, there is special syntax for indexing:

最后但并非最不重要的是,有专门用于索引的语法:

a[b]

is the same as

是一样的

a.[](b)

and

a[b] = c

is the same as

是一样的

a.[]=(b, c)

#3


8  

the square brackets are the method name like Array#size you have Array#[] as a method and you can even use it like any other method:

方括号是方法名,比如数组#size你有数组#[]作为方法,你甚至可以像其他方法一样使用它:

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

the last one is something like syntactic sugar and does exactly the same as the first one. The Array#+ work similar:

最后一个是句法糖,和第一个完全一样。数组# +工作类似:

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

You can even add numbers like this:

你甚至可以添加这样的数字:

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

the same works with /, *, - and many more.

同样适用于/、*和更多。

#4


0  

It's an operator overloader, it overrides or supplements the behavior of a method inside a class you have defined, or a class the behavior of which you are modifying. You can do it to other operators different from []. In this case you are modifying the behavior of [] when it is called on any instances of class SongList.

它是一个操作符重载器,它重写或补充您定义的类中的方法的行为,或者修改的类的行为。您可以对与[]不同的其他操作符执行此操作。在这种情况下,当调用[]类SongList的任何实例时,您正在修改[]的行为。

If you have songlist = SongList.new and then you do songlist["foobar"] then your custom def will come into operation and will assume that "foobar" is to be passed as the parameter (key) and it will do to "foobar" whatever the method says should be done to key.

如果你有歌曲列表=歌曲列表。然后你做songlist["foobar"]然后你的自定义def就会运行,并假设"foobar"将作为参数(key)传递,它将对"foobar"做任何方法说应该对key做的事。

Try

试一试

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

#1


36  

Methods in ruby, unlike many languages can contain some special characters. One of which is the array lookup syntax.

与许多语言不同,ruby中的方法可以包含一些特殊字符。其中之一是数组查找语法。

If you were to implement your own hash class where when retrieving an item in your hash, you wanted to reverse it, you could do the following:

如果你要实现你自己的哈希类,当你在哈希中检索一个条目时,你想要反向它,你可以做以下事情:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

You can prove this by calling a hash with the following:

可以通过调用散列来证明这一点:

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

So the def [] defined the method that is used when you do my_array["key"] Other methods that may look strange to you are:

因此,def[]定义了在执行my_array["key"]时使用的方法,其他可能看起来很奇怪的方法是:

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

Just to clarify, the definition of a [] method is unrelated to arrays or hashes. Take the following (contrived) example:

澄清一下,[]方法的定义与数组或散列无关。以下列(人为的)例子为例:

class B
  def []
    "foo"
  end
end

 B.new[]
 => "foo" 

#2


39  

It's just syntactic sugar. There are certain syntax patterns that get translated into message sends. In particular

只是语法糖。有一些语法模式被翻译成消息发送。特别是

a + b

is the same as

是一样的

a.+(b)

and the same applies to ==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~ and !~ as well.

同样适用于= =、! =、<、>、< =、> =、< = >、= = = &、|,*,/,,%,* *,> >,< <,! = =,= ~ ! ~。

Also,

同时,

!a

is the same as

是一样的

a.!

and the same applies to ~.

这同样适用于~。

Then,

然后,

+a

is the same as

是一样的

a.+@

and the same applies to -.

这同样适用于-。

Plus,

另外,

a.(b)

is the same as

是一样的

a.call(b)

There is also special syntax for setters:

设置程序也有特殊的语法:

a.foo = b

is the same as

是一样的

a.foo=(b)

And last but not least, there is special syntax for indexing:

最后但并非最不重要的是,有专门用于索引的语法:

a[b]

is the same as

是一样的

a.[](b)

and

a[b] = c

is the same as

是一样的

a.[]=(b, c)

#3


8  

the square brackets are the method name like Array#size you have Array#[] as a method and you can even use it like any other method:

方括号是方法名,比如数组#size你有数组#[]作为方法,你甚至可以像其他方法一样使用它:

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

the last one is something like syntactic sugar and does exactly the same as the first one. The Array#+ work similar:

最后一个是句法糖,和第一个完全一样。数组# +工作类似:

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

You can even add numbers like this:

你甚至可以添加这样的数字:

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

the same works with /, *, - and many more.

同样适用于/、*和更多。

#4


0  

It's an operator overloader, it overrides or supplements the behavior of a method inside a class you have defined, or a class the behavior of which you are modifying. You can do it to other operators different from []. In this case you are modifying the behavior of [] when it is called on any instances of class SongList.

它是一个操作符重载器,它重写或补充您定义的类中的方法的行为,或者修改的类的行为。您可以对与[]不同的其他操作符执行此操作。在这种情况下,当调用[]类SongList的任何实例时,您正在修改[]的行为。

If you have songlist = SongList.new and then you do songlist["foobar"] then your custom def will come into operation and will assume that "foobar" is to be passed as the parameter (key) and it will do to "foobar" whatever the method says should be done to key.

如果你有歌曲列表=歌曲列表。然后你做songlist["foobar"]然后你的自定义def就会运行,并假设"foobar"将作为参数(key)传递,它将对"foobar"做任何方法说应该对key做的事。

Try

试一试

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