Kernel#Array - Ruby如何解释与常量同名的方法?

时间:2017-08-02 15:57:32

标签: ruby

当我在Ruby中编码时,为了避免类型检查以及respond_to?nil检查,我经常将对象强制转换为我期望的类型。如果我期望Array,而不是foo.nil? ? handle_nil(foo) : handle_array(foo)我更喜欢仅handle_foo(foo.to_a) nil.to_a # => []。{/ p>

这不适用于所有内容,1.to_a会引发NoMethodError: undefined method 'to_a' for 1:Integer1.to_ary引发了同样的错误。 Array()似乎可以解决问题,处理看似任何对象的内容,并对Array进行合理转换或将其包装在[]中。

Array(nil)        # => []
Array('')         # => [""]
Array(Class)      # => [Class] 
Array(1)          # => [1]
Array(Object.new) # => [#<Object:0x007fdbd40df4c8>]
Array({})         # => []
Array(foo: :bar)  # => [[:foo, :bar]]

您也可以对其他课程做同样的事情。 String()Float() ...我在不考虑不寻常的语法的情况下使用了很多。我想了解有关实施的更多信息。它是一种特殊方法的语法糖,类似于#[]

这两个都会引发SyntaxError

def self.(foo)
  puts foo
end

def self.()(foo)
  puts foo
end

您使用Array()就像使用方法一样。查看Kernel的文档,很明显,这就是正在发生的事情。以下工作正如您所期望的那样:

class Thing
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

module Kernel
  def Thing(name)
    Thing.new(name)
  end
end

thing = Thing('name') # => #<Thing:0x007fefef89d8e8 @name="name">
thing.name # => "name"

你也可以这样做

HI = 'hi'.freeze

def HI(word)
  word
end

HI       # => "hi"
HI("ho") # => "ho"

我的问题是:Ruby如何解释这个?它如何区分方法和常数?这是一个愚蠢的问题吗?鉴于“正常”行为,人们可能希望Ruby在您定义方法时引发名称警告,或者引发SyntaxError。有谁知道Ruby如何处理这个问题?

谢谢!

1 个答案:

答案 0 :(得分:3)

  

Ruby如何解释这个?它如何区分方法和常数?

规则与局部变量几乎相同:Ruby会假设它是一个常量,除非它显然不是:常量不能有参数,而常量不能有接收器。

FOO      # constant
self.FOO # message send
FOO()    # message send
FOO :bar # message send
  

鉴于“正常”行为,人们可能希望Ruby在定义方法时抱怨名称警告,或者提出SyntaxError

为什么呢?定义一个方法在语法上是完全合法的(毕竟,这就是OO的全部意义),Array是完全合法的Ruby标识符。