'<<'作为常规方法
在大多数情况下,'<<'是与其他方法一样定义的方法,在您的情况下,它的意思是“添加到此数组的末尾”(另请参见此处)。
这是在您的特定情况下,但在其他许多情况下,您也会遇到“ <<”方法。我不会称其为“运算符”,因为它实际上是在某些对象上定义的方法,可以被您覆盖或为您自己的对象实现。其他情况“ <<”
- 字符串串联:“ a” <<“ b”
- 将输出写入IO:io <<“一行文本\ n”
- 将数据写入消息摘要,HMAC或密码:sha <<“要散列的文本”
- OpenSSL :: BN的左移:bn << 2
- ...
单例类定义
然后程序流中当前范围的神秘变化(=自身的变化):
class A
class << self
puts self
end
end
a = A.new
class << a
puts self
end
这个谜class << self
使我感到疑惑,并调查了那里的内部构造。而在所有示例中,我提到<<
的实际上是在类中定义的方法,即
obj << stuff
相当于
obj.<<(stuff)
该class << self
构建体(代替自或任何对象)是真正的不同。它实际上是语言本身的内置功能,在CRuby中,它在parse.y中定义为
k_class tLSHFT expr
其中tLSHFT是'<<'令牌,k_class是'class'关键字,而expr是任意表达式。也就是说,你实际上可以写
class << <any expression>
并将“转移”到表达式结果的单例类中。tLSHFT序列将被解析为“ NODE_SCLASS”表达式,称为“单例类”定义(请参阅node.c)
case NODE_SCLASS:
ANN("singleton class definition");
ANN("format: class << [nd_recv]; [nd_body]; end");
ANN("example: class << obj; ..; end");
F_NODE(nd_recv, "receiver");
LAST_NODE;
F_NODE(nd_body, "singleton class definition");
break;
这里文件
而且,我怎么会忘记这些,这里的文档以完全不同的方式使用“ <<”。您可以通过声明以下内容来方便地定义跨越多行的字符串:
here_doc = <<_EOS_
The quick brown fox jumps over the lazy dog.
...
_EOS_
为了区分“ here doc operator”,必须使用任意的字符串定界符紧跟在“ <<”之后。在该初始定界符和该定界符的第二次出现之间的所有内容都将成为最终字符串的一部分。也可以使用'<<-',不同之处在于使用后者将忽略任何前导或尾随空格。