我遇到了漂亮而美丽的代码。基本上,如果我定义一个根本不会实例化的类,我会做这样的事情:
class Foo
def self.bar
# Do something
end
end
但是,这个语法困扰着我(必须将self.
放在每种方法中),所以Singleton解决了我的问题:
class Foo
class << self
def bar
# Do something, but in better code
end
end
end
在这两种方面,我都可以做Foo.bar
,它会做点什么,但是第一个看起来不好,在第二个我仍然不明确地工作,所以更好地小心,不要使用使用它。
所以,最后...我想问什么:除了上述提到的外,还有办法做Foo.bar
吗?
(EngineersMnky在评论中已经提到了这一点)
您可以使用保存您的类方法的模块扩展课程(该模块可以嵌套在类中):
class Foo
module ClassMethods
def bar
# Do something
end
end
extend ClassMethods
end
即使在自己的文件中,您也可以将其移到课外(这在结构上可能是有用的,或者如果有许多类方法):
# foo/class_methods.rb
class Foo
module ClassMethods
def bar
# Do something
end
end
end
# foo.rb
class Foo
extend ClassMethods
end
通过extend
定义的方法甚至可以在基类中覆盖:
class Foo
module ClassMethods
def bar
123
end
end
end
class Foo
extend ClassMethods
def self.bar
super * 2
end
end
Foo.bar #=> 246
如果要在使用同一模块扩展多个类时(考虑共享类方法)时,这特别有用。
以下是我在评论中提到的深奥元编程技术的示例:
module Foo
instance_eval do
def bar
'baz'
end
end
end
现在调用新方法:
Foo.bar
=> 'baz'
instance_eval
的使用是不直觉的,因为它是用于定义类方法的,而 class_eval
是例如方法。
对于Cary提到的技术也有类似的方法(尽管他使用define_method
,例如,对于类方法而言,这是方法与define_singleton_method
):
module Foo
define_singleton_method(:bar) do
'baz'
end
end
调用该方法相同:
Foo.bar
=> 'baz'
但同样,这些是您永远不会以这种方式使用的高级技术,因为有更简单的标准方法可以完成相同的任务(并且您在问题中给出了两个示例)。如果您尝试以这种方式定义所有类方法,那么阅读它的任何人都会丑陋,重复和混乱。
所显示的技术通常由代码 furece 使用定义的模块/类,因此您可以在不需要直接修改其源代码的情况下对其进行操作,有时称为Monkey Patching。/p>
例如,如果没有方法定义模块:
module Foo
end
您可以在其他任何地方都说Foo.instance_eval {}
或Foo.define_singleton_method(:bar) {}
,然后将其适用于Foo
。当您想挫败Foo
尝试封装的作者时,这很有用。
,如果我不清楚,我在这里显示的示例是您应该不是做的。当需要对类/模块的动态更改时,它们会使用它们。那不是你描述的。