我正在通过Service Objects阅读关于Dave Copeland的博文,并发现了以下内容:
Ruby中的类是全局符号,这意味着类方法是全局符号。编码为全局变量是我们不再使用PHP的原因。
我想更多地理解这个陈述并提出一些问题。
例如,参加以下irb会话:
irb(main):001:0> Symbol.all_symbols.grep /Foo/
=> []
irb(main):002:0> Symbol.all_symbols.grep /some.*method/
=> []
irb(main):003:0> class Foo
irb(main):004:1> def some_instance_method; end
irb(main):005:1> def self.some_class_method; end
irb(main):006:1> end
=> :some_class_method
irb(main):007:0> Symbol.all_symbols.grep /Foo/
=> [:Foo]
irb(main):008:0> Symbol.all_symbols.grep /some.*method/
=> [:some_instance_method, :some_class_method]
#some_instance_method
和::some_class_method
在符号上下文中有何不同?Symbol.all_symbols
时,我在做什么,这与查看"全局符号"?为什么显示#some_instance_method
和::some_class_method
?在阅读了上述引用后,我预计008
的结果为:
IRB(主):008:0> Symbol.all_symbols.grep /some.*method/ => [:some_instance_method]
答案 0 :(得分:1)
我认为Dave对他所说的方式有点不清楚,但他解释了你摘录后段落中的影响:
服务作为全球符号存在问题的一个很好的例子是Resque。所有Resque方法都可以通过Resque获得,这意味着任何Ruby VM都只有一个可以使用的resque。
[...]
另一方面,如果将Resque实现为一个对象而不是全局,那么任何需要访问不同Resque实例的代码都不必更改 - 它只会被赋予一个不同的对象。
不同之处在于界面:使用Resque,工具的用户“依赖”并与特定类接口 - 它们是对象,但它们是作为全局变量处理的对象。这与对象上的实例方法的接口相反,其中任何其他对象可以在不依赖于对象的类的情况下被加入。
因此,在全局(如无范围的类定义)上使用类方法是,Dave认为,类似于使用全局方法,即PHP。
答案 1 :(得分:1)
我发现该文有几个问题:
首先,使用" symbol"可能会令人困惑。事实上,这个词确实完美地描述了作者的意思,但有些读者可能会将其与Ruby中的Symbol
数据类型混淆。因此,虽然不是错误的,但在Ruby的上下文中,单词的选择是不幸的。 "名称"可能是一个更好的选择。
其次,他在类和实例方法之间进行了人为的区分,但在Ruby中没有类方法这样的东西。 Ruby只有一种方法:实例方法。我们称之为"单身方法"实际上只是单例类的常规实例方法,我们称之为"类方法"实际上只是一个对象的singleton类的常规实例方法,恰好是Class
类的一个实例。
第三,他在类和对象之间进行了人为的区分,但类是Ruby中的对象。
似乎我们真的争论反对,是常量(因为它们是全局名称),单例(通常是哪些类)和静态。虽然所有这些都是坏的当然是正确的,但他应该这样说,如果那是他的意思。 (它也不是一个新发现;整个编程语言都是基于避免静态设计的,例如Newspeak。)
tl; dr summary :这篇文章反对全球名称,单身人士和静态,但却被严重地呈现和表达。
答案 2 :(得分:1)
:some_instance_method
和:some_class_method
符号仅存在于Ruby的符号表中。它们在符号的上下文中不不同。 Symbol.all_symbols
结果不会声明有关被引用对象的任何内容。如果你有:
class Aaa
def kick_it
logger.debug { "You kicked an Aaa object" }
end
end
module Bbb
def self.kick_it
logger.debug { "You kicked Bbb" }
end
end
:kick_it
只会报告1 Symbol.all_symbols
,即使其中一个是模块级方法而另一个是实例方法。
使用"符号"在文章中可能令人困惑。 A"全球符号"这可能意味着集合Object.constants
的成员的名称,或者在定义的常量子树中可访问的任何其他常量。
因此Symbol.all_symbols
与"全局符号"不同。在这种情况下。但是,内存常量树中的所有名称都是Symbol.all_symbols
的子集,请记住,那里的所有范围信息都会丢失。
我认为上面的问题1 答案也解释了为什么两个符号都显示在Symbol.all_symbols
结果中。