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