Ruby中的私有模块方法

Dan*_*ley 99 ruby access-specifier private-methods

我有两个问题

最佳实践

  • 我有一个算法,使用公共接口对数据结构执行某些操作
  • 它目前是一个具有许多静态方法的模块,除了一个公共接口方法之外都是私有的.
  • 有一个实例变量需要在所有方法之间共享.

这些是我能看到的选项,哪个最好?:

  • 模块与静态(红宝石"模块")的方法
  • 使用静态方法的
  • Mixin模块包含在数据结构中
  • 重构修改该数据结构的算法部分(非常小)并使其成为调用算法模块的静态方法的mixin

技术部分

有没有办法制作私有模块方法

module Thing
  def self.pub; puts "Public method"; end
  private
  def self.priv; puts "Private method"; end
end
Run Code Online (Sandbox Code Playgroud)

private中似乎有没有什么影响,我仍然可以调用Thing.priv没有问题.

小智 85

我认为最好的方法(以及主要是如何编写现有的lib)通过在模块中创建一个处理所有逻辑的类来实现这一点,并且模块只提供了一个方便的方法,例如

module GTranslate
  class Translator
    def perform( text ); 'hola munda'; end
  end

  def self.translate( text )
    t = Translator.new
    t.perform( text )
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 我不确定在这里上课有什么成就.如果目标是拥有私有模块方法,那么这不符合目标.因为您可以通过调用GTranslate :: Translator.new.perform从模块外部访问"perform"方法.换句话说,它不是私人的. (22认同)
  • Ruby newb在这里.在这个例子中,Translator类是作为模块的公共接口的一部分公开的吗?"执行"方法的访问权限是否仅限于GTranslate? (14认同)
  • `GTranslate :: Translator.new.perform(text)` - 复杂但不私密! (4认同)
  • @rshepherd `perform` 不是这里应该是私有的方法,私有方法是 `Translator` 类中的私有方法(@ucron 的例子没有,很可惜)。`GTranslate.translate` 只是 `GTranslate::Translator#perform` 的一种方便的方法,如果可能的话,并没有真正的增益来隐藏它。 (2认同)

小智 75

还有Module.private_class_method,可以说表达了更多的意图.

module Foo
  def self.included(base)
    base.instance_eval do
      def method_name
        # ...
      end
      private_class_method :method_name
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

对于问题中的代码:

module Thing
  def self.pub; puts "Public method"; end
  def self.priv; puts "Private method"; end
  private_class_method :priv
end
Run Code Online (Sandbox Code Playgroud)

Ruby 2.1或更新版本:

module Thing
  def self.pub; puts "Public method"; end
  private_class_method def self.priv; puts "Private method"; end
end
Run Code Online (Sandbox Code Playgroud)

  • 这个答案以及[@ JCooper的答案](http://stackoverflow.com/a/318893/445221)是真正的解决方案.@ MarnenLaibow-Koser它没有.您可以考虑更多分组和缩进来考虑其他答案.它实际上可能是某些人的首选解决方案.(仅为了参考而回复.) (6认同)

cdr*_*rev 49

module Writer
  class << self
    def output(s)
      puts upcase(s)
    end

    private

    def upcase(s)
      s.upcase
    end
  end
end

Writer.output "Hello World"
# -> HELLO WORLD

Writer.upcase "Hello World"
# -> so.rb:16:in `<main>': private method `upcase' called for Writer:Module (NoMethodError)
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案.在我看来,干净和惯用. (4认同)

小智 28

您可以使用"包括"方法做花哨的东西,当一个模块中混合这确实你想要什么,我认为:

module Foo
  def self.included(base)
    class << base 
      def public_method
        puts "public method"
      end
      def call_private
        private_method
      end
      private
      def private_method
        puts "private"
      end
    end
  end
end

class Bar
  include Foo
end

Bar.public_method

begin
  Bar.private_method
rescue
  puts "couldn't call private method"
end

Bar.call_private
Run Code Online (Sandbox Code Playgroud)

  • 这很聪明.所以这是可能的,但可能不值得. (5认同)
  • @Crystark:如果我没有弄错的话,那个语法只存在于扩展ActiveSupport :: Concern的模块上.即它是一个铁路的东西. (5认同)

J C*_*per 12

不幸的是,private仅适用于实例方法.在类中获取私有"静态"方法的一般方法是执行以下操作:

class << self
  private

  def foo()
   ....
  end
end
Run Code Online (Sandbox Code Playgroud)

不可否认,我没有在模块中这样做过.

  • 这不是真的.您可以拥有私有类方法和私有模块方法. (7认同)