Codeacademy教导您可以将多种方法链接在一起:
user_input.method1.method2.method3
但是,在后面的课程中,他们会显示一些这样的方法:
user_input = gets.chomp
user_input.downcase!
我把它们结合起来:
user_input = gets.chomp.downcase!
当我以这种方式使用它时:
user_input = gets.chomp.downcase!
if user_input.include? "s"
...
我收到错误"undefined method `include?'"
。如果我将其更改为以下内容,则可以正常工作:
user_input = gets.chomp
user_input.downcase!
if user_input.include? "s"
...
我很茫然。我担心这是否是他们的控制台的怪癖,或者这是我应该如何在Ruby中做到这一点。如果有人能告诉我哪种方式是正确的,我会很感激。如果两者都是对的,那也没关系。
答案 0 :(得分:1)
首先,如果您还没有完全理解,可以通过=
为变量赋值,并且可以通过将.class
附加到任何内容来检查变量类型。
请考虑以下事项:
name = 'John'
puts name
# => John
puts name.class
# => String
现在,其次,应该注意ALL方法的返回值是完全不同的。但所有这些都可以分为两类:
方法:
1的示例
- 返回self的方法,你可以说返回相同类型对象的方法,在我们的特定情况下,String
name = 'John'
puts name
# => 'John'
puts name.class
# => String
downcased_name = name.downcase
puts downcased_name
# => john
puts downcased_name.class
# => String
deleted_downcased_name = downcased_name.delete('h')
puts deleted_downcased_name
# => jon
puts deleted_downcased_name.class
# => String
# All of the above can be just simplified into:
deleted_downcased_name2 = 'John'.downcase.delete('h')
puts deleted_downcased_name2
# => jon
puts deleted_downcased_name2.class
# => String
请注意,deleted_downcased_name
和deleted_downcased_name2
是相同的,因为您可以将链接方法视为链接返回值“John” - > 'john' - > '乔恩'。
2
的示例- 返回除self之外的任何东西的方法,你可以说返回不同类型的方法。
在我们的特定情况下,字符串的downcase!
会返回String
或NilClass
(reference here)
String
,或nil
。或其他字符串的方法:start_with?
(reference here)
true
或false
当您尝试将String方法用作nil值的链时,这就是方法链接不起作用的地方(引发错误)。
考虑以下
name = 'mary'
puts name
# => 'mary'
puts name.class
# => String
downcased_name = name.downcase!
puts downcased_name
# => nil
puts downcased_name.class
# => NilClass
downcased_name.delete('h')
# => This will raise the following error
# NoMethodError: undefined method `delete' for nil:NilClass
上面的错误是因为downcased_name是NilClass
的一种类型,您希望它是String
的类型。因此,您不能再在其上链接任何字符串方法。您只能在String
类型的值上链接String
个方法。同样,您只能在Number
类型的值上链接Number
个方法。
每当有疑问时,您都可以随时查看文档以检查方法的作用以及返回值和类型。
答案 1 :(得分:0)
您遇到的问题是使用爆炸方法downcase!
。
这基本上是说"改变原始字符串,使其为小写"。
重要的是返回nil
。因此,您实际上是在include?
上调用nil
。
如果您使用非爆炸方法downcase
,它会说"对先前链接的东西进行倒置,但不要改变原始"。关键区别在于它返回的结果而不是nil
。
以下是一个例子:
str = "ABCD"
str.downcase!
=> nil
str
=> "abcd"
str = "ABCD"
str.downcase
=> "abcd"
str
=> "ABCD" # Note str is still unchanged unless you set str = str.downcase
答案 2 :(得分:0)
欢迎来到Ruby!虽然您在Codeacademy的学徒期可能有限,但您将在整个职业生涯中继续参考语言API文档。 API文档描述了语言(或库)为您所做的事情。在这种情况下,您正在使用downcase!,正如一位评论者指出的那样,它并不总是返回一个字符串。当它不采取任何行动时,它返回零。 Nil是Ruby中的一个对象(就像其他所有东西一样),但是'include?'没有为nil定义方法,这解释了你的错误。 (这是Ruby中最常见的错误之一,了解其含义。)
所以,事实上,这里打破的不是你的方法链。这是其中一个中间方法没有返回你期望的类型的值(nil而不是某种String)。
答案 3 :(得分:0)
链接非破坏性方法,如:
string.chomp.downcase...
的优点是代码简洁,但如果您对对象的原始状态不感兴趣,并且只想要最终结果,因为它在链中创建了中间对象,效率不高。
另一方面,将破坏性方法依次应用于同一对象:
string.chomp!
string.downcase!
...
如果你不需要保持对象的原始状态,那么会更有效率,但是不简洁。
将可能返回不同类的对象(特别是nil
)的方法组合为:
string = gets.chomp!.downcase!...
是错误的,因为结果可能会在链中的某个点变为nil
。
在您最后的位置应用可能的nil
- 返回方法:
string = gets.chomp.downcase!
如果您希望string
始终是一个字符串,仍然无用,并且很容易导致错误。
如果你想在你的例子中链接这些方法,也许你可以这样做:
user_input = gets.tap(&:chomp!).tap(&:downcase!)
if user_input.include?("s")
...