Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ruby中最烦人的类方法怪癖_Ruby_Scope_Singleton - Fatal编程技术网

ruby中最烦人的类方法怪癖

ruby中最烦人的类方法怪癖,ruby,scope,singleton,Ruby,Scope,Singleton,你能在下面的代码中发现问题吗 module F def f(x) return x*x end end class Test3 include F def self.ok(x) return f(2*x) end end 这个怎么样 class Test1 def f(x) return x*x end def Test1.ok(x) return f(2*x) end end 或者甚至是这个 class Te

你能在下面的代码中发现问题吗

module F
  def f(x)
    return x*x
  end
end

class Test3
  include F
  def self.ok(x)
    return f(2*x)
  end
end
这个怎么样

class Test1
   def f(x)
     return x*x
   end
   def Test1.ok(x)
     return f(2*x)
   end
end
或者甚至是这个

class Test2
   def self.ok(x)
     def f(x)
       return x*x
     end
     return f(2*x)
   end
end

这完全不是直觉。为什么Ruby在任何一种情况下都找不到“f”?

与许多面向对象语言一样,Ruby在类上下文中的方法和实例上下文中的方法之间有分离:

当使用其本机上下文调用它们时,它会起作用:

Example.a_class_method
Example.new.an_instance_method
在错误的上下文中调用它们时,会出现错误:

Example.new.a_class_method # => No such method
Example.an_instance_method # => No such method
由于实例与类相关,因此可以执行以下操作:

Example.new.class.a_class_method # => Works!
这通常在需要使用类方法的实例方法内部完成。类方法不能真正利用实例方法,除非有实例在使用。当决定做出一个方法时,你经常需要考虑它将被使用的上下文。如果它与实例相关,特别是如果它使用
@
-样式的实例变量,那么它就是一个实例方法。如果它是一个通用实用程序方法,打算独立于任何特定实例使用,那么它就是一个类方法

在其他语言中,类方法被称为“静态”方法,它们基本上是独立的,但在Ruby中,它们实际上与类本身相关,类本身是一个特殊的对象,因此有时会有点混淆


这就是为什么在定义中注意self的存在是非常重要的。

因为我们不能直接从class方法得到f,所以有一些选择是有意义的。首先,将“f”降级

class Test1
   def self.f(x)
     return x*x
   end
   def self.ok(x)
     return f(2*x)
   end
end
其次是最麻烦的案件。显然,函数的作用域与变量的作用域不同,即使在同一行上定义。在这里,将f定义为一个变量,我们可以正确地访问它。大多数语言都支持闭包。Ruby有块。然而,由于它的无括号调用约定,如果没有晦涩的语法,它永远不会有thunks

class Test2
   def self.ok(x)
     f = lambda {|x| x*x}
     return f.call(2*x)
   end
end

module F
  def f(x)
    return x*x
  end
end
最后,include可以在范围中降级。双倍包括任何人吗

class Test3
  class << self
    include F
  end
  def self.ok(x)
    return f(2*x)
  end
end
类Test3

类它不是Ruby无法找到
f
,而是您让它在错误的位置查找;)请查看有关范围/上下文的一些资料。了解什么是
self
。然后你会自己回答你的问题:)那么你能评论第三种情况吗?请看这条线索你的问题是你试图混合类和实例方法。如果你不能费心去理解什么是类、实例、模块和方法,这只是一个恼人的怪癖。有了这种程度的分离,我现在想知道为什么有人会使用class方法而不是编写一个模块来保存所有这些静态函数。类也是一个模块,所以有时候在类本身中组织东西更容易。例如:
Company.count
Company.new.name
来自ActiveRecord。另一个问题是
Regexp.escape
如何处理任意输入,它是一个实用函数,但是
Regexp.new(…).match(…)
是一个实例方法,它只对上下文的正则表达式有意义。Ruby非常强大的一点是它的表达能力,如何恰当地命名和组织代码,代码本身就能很好地传达意图。将事物置于抽象层之下会混淆其含义
Company::DataStore.current.count_instances
是朝相反方向迈出的一步,即使它在功能上做了相同的事情。“与许多面向对象的语言一样,Ruby将类上下文中的方法与实例上下文中的方法分离”——实际上,Ruby非常独特,因为它没有不同的方法。所有方法都是实例方法。问题是:它们是在哪一类中定义的?@JörgWMittag我在这里过于简化,试图澄清。从技术上讲,它们是类实例变量,但对于任何不了解全部情况的人来说,这都很奇怪。在接近尾声时,我确实试着暗示了这一点。
class Test3
  class << self
    include F
  end
  def self.ok(x)
    return f(2*x)
  end
end