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

Translate

我正在经历Ruby编程-实用的程序员指南并偶然发现了这段代码:

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

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

为什么键位于[]之外,但是调用该方法时却位于[]内部?

密钥可以不带括号吗?

我意识到有更好的方法来编写此代码,并且知道如何编写自己的有效方法,但是此[]方法让我感到困惑...非常感谢您的帮助,谢谢

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

所有的回答

Translate

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

如果要实现自己的哈希类,则在其中检索哈希中的项目时,您想反转它,则可以执行以下操作:

class SillyHash < Hash

  def [](key)
    super.reverse
  end

end

您可以通过使用以下代码调用哈希来证明这一点:

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

因此,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

只是澄清一下,[]方法与数组或哈希无关。采取以下(人为)示例:

class B
  def []
    "foo"
  end
end

 B.new[]
 => "foo" 
来源
Translate

这只是语法糖。有某些语法模式可以转换为消息发送。特别是

a + b

是相同的

a.+(b)

同样适用于==, !=, <, >, <=, >=, <=>, ===, &, |, *, /, -, %, **, >>, <<, !==, =~!~也一样

也,

!a

是相同的

a.!

同样适用于~.

然后,

+a

是相同的

[email protected]

同样适用于-.

加,

a.(b)

是相同的

a.call(b)

二传手也有特殊的语法:

a.foo = b

是相同的

a.foo=(b)

最后但并非最不重要的一点是,有特殊的索引语法:

a[b]

是相同的

a.[](b)

a[b] = c

是相同的

a.[]=(b, c)
来源
Translate

方括号是方法名称,例如Array#size你有Array#[]作为一种方法,甚至可以像其他任何方法一样使用它:

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

最后一个类似于语法糖,其功能与第一个完全相同。的Array#+工作类似:

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

您甚至可以添加如下数字:

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

相同的作品/, *, -还有很多。

来源
Translate

它是一个运算符重载程序,它重写或补充您已定义的类或要修改其行为的类中方法的行为。您可以对[]以外的其他运算符执行此操作。在这种情况下,您正在修改在SongList类的任何实例上调用[]时的行为。

如果您具有songlist = SongList.new,然后执行songlist [“ foobar”],则您的自定义def将开始运行,并假定“ foobar”将作为参数(键)传递,并且将对“ foobar”进行传递“无论方法说什么,都应该做关键。

尝试

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
来源
Leave a Reply
You must be logged in to post a answer.
关于作者