我在编写漂亮代码方面遇到了麻烦。基本上,如果我定义了一个根本不会实例化的类,我会做这样的事情:
class Foo
def self.bar
# Do something
end
end
但是这种语法使我感到困扰(必须在每种方法中放入self.
),因此单例解决了我的问题:
class Foo
class << self
def bar
# Do something, but in better code
end
end
end
在两种方式下,我都可以做Foo.bar
并且可以做点事,但是第一个看起来不太好,在第二个中,我仍然不了解单例的确切工作方式,因此最好小心而不要使用它。
所以,最后...我想问的是:除了上述内容,还有其他方法可以Foo.bar
吗?
答案 0 :(得分:1)
这是我在评论中提到的深奥元编程技术的示例:
module Foo
instance_eval do
def bar
'baz'
end
end
end
现在调用新方法:
Foo.bar
=> 'baz'
instance_eval
的用法是unintuitive,因为它是用于定义类方法的,而class_eval
是用于实例方法的。
Cary提到的技术也有类似的方法(尽管他使用define_method
来代替实例方法,而define_singleton_method
是用于类方法):
module Foo
define_singleton_method(:bar) do
'baz'
end
end
调用该方法的原理相同:
Foo.bar
=> 'baz'
但是,这些都是高级技巧,您将永远不会以这种方式使用它们,因为完成相同任务的标准方法要简单得多(并且您在问题中举了两个例子)。如果您尝试以这种方式定义所有的类方法,那将是丑陋的,重复性的,并使阅读它的任何人感到困惑。
所示的技术通常由代码外部在已定义的模块/类中使用,因此您可以在外部进行操作而不必直接修改其源代码,有时称为{{3} }。
例如,如果模块没有定义方法:
module Foo
end
您可以在其他任何地方的代码中用Foo.instance_eval {}
或Foo.define_singleton_method(:bar) {}
表示,此后将适用于Foo
。当您想挫败Foo
尝试monkey patching的作者时,这很有用。
如果我不清楚,这里显示的示例是您不应该做的。当需要动态更改类/模块时使用它们。那不是你所描述的。
答案 1 :(得分:1)
(engineersmnky in the comments已经提到过)
您可以使用包含您的类方法的模块扩展您的类(该模块可以嵌套在您的类中):
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
如果要在使用同一模块扩展多个类时想添加自定义功能(这是共享类方法),这将特别有用。