Ruby中的私有模块方法

我有两个部分的问题

最佳实践

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

这些是我可以看到的选项,哪个最好?

  • 模块与静态(ruby模块)的方法
  • 与静态方法
  • Mixin模块包含在数据结构中
  • 重构出修改该数据结构的algorithm部分(非常小),并调用一个调用algorithm模块静态方法的mixin

技术部分

有没有办法做一个私人的模块方法

module Thing def self.pub; puts "Public method"; end private def self.priv; puts "Private method"; end end 

那里的private似乎没有任何影响 ,我仍然可以叫Thing.priv没有问题。

我认为最好的方式(主要是如何编写现有的库)是通过在处理所有逻辑的模块中创build一个类来实现的,模块只是提供一个方便的方法,例如

 module GTranslate class Translator def perform( text ); 'hola munda'; end end def self.translate( text ) t = Translator.new t.perform( text ) end end 

还有Module.private_class_method ,可以expression更多的意图。

 module Foo def self.included(base) base.instance_eval do def method_name # ... end private_class_method :method_name end end end 

对于问题中的代码:

 module Thing def self.pub; puts "Public method"; end def self.priv; puts "Private method"; end private_class_method :priv end 

Ruby 2.1或更新版本:

 module Thing def self.pub; puts "Public method"; end private_class_method def self.priv; puts "Private method"; end end 

你可以使用“包含”的方法做一些混合模块时的花哨的东西。这就是你想要的东西,我想:

 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 
 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) 

不幸的是, private只适用于实例方法。 在一个类中获得私有“静态”方法的一般方法是做如下的事情:

 class << self private def foo() .... end end 

诚然,我还没有玩过这个模块。

一个好方法就是这样

 module MyModule class << self def public_method # you may call the private method here tmp = private_method :public end private def private_method :private end end end # calling from outside the module puts MyModule::public_method 

我在Rails中发现的最好的模式就是放弃那些想要私有方法并使用Singleton类的模块。 它感觉不对,但它确实起作用,并且看起来比我在这个问题中看到的其他例子更清洁。

很想听到其他意见。

例:

 ErrorService.notify("Something bad happened") class ErrorService include Singleton class << self delegate :notify, to: :instance end def notify(message, severity: :error) send_exception_notification(message) log_message(message, severity) end private def send_exception_notification(message) # ... end def log_message(message, severity) # ... end end 

制作私人模块或课程

常量永远不是私有的。 但是,可以创build一个模块或类,而不必将其分配给常量。

因此, :private_class_method的另一种方法是创build一个私有模块或类,并在其上定义公共方法。

 module PublicModule def self.do_stuff(input) @private_implementation.do_stuff(input) end @private_implementation = Module.new do def self.do_stuff(input) input.upcase # or call other methods on module end end end 

用法:

 PublicModule.do_stuff("whatever") # => "WHATEVER" 

查看Module.new和Class.new的文档。

在类variables/常量中将方法存储为lambdas是什么?

 module MyModule @@my_secret_method = lambda { # ... } # ... end 

testing:

 module A @@C = lambda{ puts "C" } def self.B ; puts "B"; @@C[] ; end private # yeah, this has no sense, just for experiment def self.D ; puts "D"; @@C[] ; end end for expr in %w{ A::B AB A::C AC A::D AD } eval expr rescue puts expr end 

这里我们看到C可以被B和D成功使用,但是不能从外部使用。