我是ruby的新手并且做了一些基本的字符串操作以获得它的挂起而且我注意到foo = 'foo'.downcase!
与向foo
这样的值分配后的下行情况不同:
foo = 'foo'.downcase!
if foo.include? 'foo'
print 'bar'
end
这将产生NoMethodError
:undefined method `include?' for nil:NilClass (NoMethodError)
在分配值后下调foo时不会:
foo = 'foo'
foo.downcase!
if foo.include? 'foo'
print 'bar'
end
我很抱歉,如果这是一个微不足道的问题,但几分钟的谷歌搜索并没有带来任何丰硕成果。
答案 0 :(得分:5)
这是因为String#downcase!
是一种破坏性的方法(因此!)意味着它在适当的对象上运行。由于它改变了对象本身,因此它的返回值不是必需的。 Ruby设计者决定好好使用返回值来指示是否进行了任何更改。
下载str的内容,如果没有进行任何更改则返回nil。
您的字符串已经是小写字母,因此downcase!
会返回nil
,然后您将变量替换为。{/ p>
答案 1 :(得分:2)
String#downase!
会返回nil
。这就是foo = 'foo'.downcase!
导致局部变量foo
被称为nil
的原因。因为foo
字符串已经下降了。
这就是if foo.include? 'foo'
成为if nil.include? 'foo'
的原因。我们知道Nilclass#include?
不存在,所以你得到了错误。
但String#downcase
会返回接收者本身,如果无法进行任何更改,或更改新的字符串对象,如果可以进行更改。
在下面的示例中:
downcase!
方法返回nil
(我在第一段中提到的原因),但是你没有做局部变量赋值,而你正在调用方法(这是您的第一个示例的情况),因此foo
仍保留原始对象'foo'
。
foo = 'foo'
foo.downcase!
这就是if foo.include? 'foo'
成为if "foo".include? "foo"
的原因。但是你在#include?
上调用了'foo'
一个String实例,并且存在String#include?
方法,因此没有错误。
答案 2 :(得分:1)
由于这一点,你看到了这种行为:
'foo'.downcase!
downcase!
方法是就地替换,这意味着它仅影响调用它的对象。它只会在更改字符串时返回结果。例如......
foo = 'foo'.downcase! # foo == NilClass, because 'foo' is already lower-case.
bar = 'BAR'.downcase! # bar == String, because 'BAR' was changed to 'bar'
如果您需要保证在执行小写操作后foo
是一个字符串,则可以使用非侵入式downcase
方法(请注意缺少的感叹号)。
foo = 'foo'.downcase
if foo.include? 'foo'
print 'bar'
end
以上代码应始终有效。作为一项规则,使用字符串作为不可变的通常是一个好主意,而不是使用侵入式方法,因为它可以大大简化代码,并避免这样的错误。