不在每个类方法中使用自我,也不使用Ruby中的单例模型



我遇到了漂亮而美丽的代码。基本上,如果我定义一个根本不会实例化的类,我会做这样的事情:

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尝试封装的作者时,这很有用。

,如果我不清楚,我在这里显示的示例是您应该不是做的。当需要对类/模块的动态更改时,它们会使用它们。那不是你描述的。

最新更新