Ruby的按位移位运算符“<<”混乱

时间:2015-09-21 19:21:01

标签: ruby-on-rails ruby

我正在研究Ruby,无法解决这个问题。我有一个练习,我必须在包含游戏的Library类中添加一个方法。每个游戏都是一个类游戏的实例。所以解决方案如下:

class Library
  attr_accessor :games

  def initialize(games)
    self.games = games
  end

  def has_game?(search_game)
    for game in games
      return true if game == search_game
    end
    false
  end

  def add_game(game)
    @games << game
  end
end

我无法理解<<在这种情况下的工作原理。这是一个按位左移吗?库类只假设games是一个数组,我相信在初始化,单个游戏或一系列游戏时我可以将任何东西传递给Library类吗?

3 个答案:

答案 0 :(得分:5)

当你有:

@games << game

<<实际上是一种方法。如果这是一种方法,你会问,为什么不以正常的方式写出来:

@games.<<(game)

?事实上,你可以这样写它,它会工作正常。许多Ruby方法的名称都是符号。其他一些是+-**&||%。 Ruby知道你更喜欢写2+3而不是2.+(3),所以她让你做前者(然后悄悄地把它转换成后者)。这种住宿通常被称为“语法糖”。

<<@games'方法之一(而game<<的参数),因为@games是方法<<接收器(技术上:<<)。从历史上看,它被称为“接收器”,因为通过OOP,您可以将方法“发送”到接收器。

<<@games的方法,意味着<<@games类的实例方法。因此,我们有:

@games.methods.include?(:<<) #=> true
@games.class.instance_methods.include?(:<<) #=> true

我希望@games是类Array的一个实例。列出了Array的实例方法here。例如:

@games = [1,2,3]
@games.class     #=> [1,2,3].class => Array
@games << 4      #=> [1,2,3,4]
@games.<<(5)     #=> [1,2,3,4,5]

另一方面,假设@gamesFixnum的实例。例如:

@games = 7
@games.class     #=> 7.class => Fixnum

二进制文件中的内容如下:

@games.to_s(2)   #=> "111"

然后:

@games << 2      #=> 28
28.to_s(2)       #=> "11100"

因为<<是类Fixnum的实例方法。

作为第三个例子,假设@games是哈希:

@games = { :a => 1 }
@games.class     #=> { :a => 1 }.class => Hash

然后:

@games << { :b => 2 }
  #=> NoMethodError: undefined method `<<' for {:a=>1}:Hash

错误消息中显示问题。类Hash没有实例方法<<

最后一件事:考虑方法Object#send。回想一下,在开始时,我说方法被发送到接收器。而不是写:

@games = [1,2,3]
@games << 4         #=> [1,2,3,4]
你可以写:

@games.send(:<<, 4) #=> [1, 2, 3, 4] 

这是你应该如何看待方法和接收器。因为send是类Object的实例方法,并且所有对象都继承了Object的实例方法,所以我们看到send正在“发送”一个方法({{ 1}},也可以表示为字符串:<<)及其参数(此处只是"<<")到接收者。

有时候,必须使用4来调用方法时。例如,send适用于sendprivate方法。另一方面,当您想要动态调用方法时,可以使用protected,其中方法的名称是变量的值。

总而言之,要了解send的作用:

method

receiver.method(*args) 的类中查找实例方法method的文档。例如,如果您使用Google“ruby数组”,则第一个匹配可能是类receiver的{​​{3}}。

答案 1 :(得分:2)

这不是一个按位左移,它是“铲”操作员。您可能知道,在Ruby中,运算符是作为方法实现的,即在您编写时

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
   {
     return resources.getDrawable(id, context.getTheme()); 
   } 
 else 
  {
    return resources.getDrawable(id); 
  }

实际发生了什么:

1 + 1

“shovel”(1.+(1) )运算符也是如此,它只是一个method on Array类,它将参数附加到数组的末尾并返回数组本身,因此它可以是链:

<<

答案 2 :(得分:1)

看起来@games是一个数组。数组的移位运算符将元素添加到数组的末尾,类似于array#push

  

ary&lt;&lt; obj→ary

     

追加 - 将给定对象推送到此数组的末尾。该表达式返回数组本身,因此可以将多个附加链接在一起。