代码之家  ›  专栏  ›  技术社区  ›  Daniel Beardsley

Ruby中的私有模块方法

  •  93
  • Daniel Beardsley  · 技术社区  · 17 年前

    我有一个由两部分组成的问题

    • 有一个实例变量需要在所有方法之间共享。

    • 单元 使用静态(ruby中的('module')方法
    • 用静态方法
    • 用于包含到数据结构中的模块
    • 重构

    有什么办法可以让你的孩子

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

    这个 private ,我仍然可以打电话 Thing.priv 毫无疑问。

    9 回复  |  直到 12 年前
        1
  •  94
  •   Ngoral    6 年前

    我认为实现这一点的最佳方法(主要是现有lib的编写方式)是在模块内创建一个处理所有逻辑的类,而模块只是提供了一个方便的方法,例如。

    module GTranslate
      class Translator
        def perform( text ); translate( text ); end
    
        private
    
        def translate( text )
          # do some private stuff here
        end
      end
    
      def self.translate( text )
        t = Translator.new
        t.perform( text )
      end
    end
    
        2
  •  83
  •   konsolebox    11 年前

    还有 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
    

    关于问题中的代码:

    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
    
        3
  •  66
  •   cdrev    10 年前
    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)
    
        4
  •  28
  •   Cameron Price    17 年前

    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
    
        5
  •  11
  •   J Cooper    17 年前

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

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

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

        6
  •  3
  •   Tallak Tveide    11 年前

    一个好方法就是这样

    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
    
        7
  •  2
  •   Gerry Shaw    6 年前

    module Thing
      extend self
    
      def pub
        puts priv(123)
      end
    
      private
      
      def priv(value)
        puts "Private method with value #{value}"
      end
    end
    
    Thing.pub
    # "Private method with value 123"
    
    Thing.priv
    # NoMethodError (private method `priv' called for Thing:Module)
    
        8
  •  1
  •   Nakilon earlonrails    7 年前

    在类变量/常量中将方法存储为lambda有什么意义?

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

    对于测试:
    UPD:这段代码在6年后进行了巨大的更新 d

    module A
      @@L = lambda{ "@@L" }
      def self.a ; @@L[] ; end
      def self.b ; a ; end
    
      class << self
        def c ; @@L[] ; end
        private
        def d ; @@L[] ; end
      end
      def self.e ; c ; end
      def self.f ; self.c ; end
      def self.g ; d ; end
      def self.h ; self.d ; end
    
      private
      def self.i ; @@L[] ; end
      class << self
        def j ; @@L[] ; end
      end
    
      public
      def self.k ; i ; end
      def self.l ; self.i ; end
      def self.m ; j ; end
      def self.n ; self.j ; end
    end
    
    for expr in %w{ A.a A.b A.c A.d A.e A.f A.g A.h A.i A.j A.k A.l A.m A.n }
      puts "#{expr} => #{begin ; eval expr ; rescue => e ; e ; end}"
    end
    

    在这里我们看到:

    A.a => @@L
    A.b => @@L
    A.c => @@L
    A.d => private method `d' called for A:Module
    A.e => @@L
    A.f => @@L
    A.g => @@L
    A.h => private method `d' called for A:Module
    A.i => @@L
    A.j => @@L
    A.k => @@L
    A.l => @@L
    A.m => @@L
    A.n => @@L
    

    1) @@L 无法从外部访问,但几乎可以从任何地方访问
    class << self ; private ; def 成功地实现了该方法 D 从外部和内部无法使用 self.
    3) private ; self. private ; class << self 不要将方法设置为私有的——它们在有和无条件下都是可访问的 自己

        9
  •  0
  •   Nathan Long    9 年前

    创建专用模块或类

    常数永远不是私有的。但是,可以创建模块或类,而无需将其分配给常量。

    因此,这是一个替代方案 :private_class_method

    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 .

        10
  •  0
  •   jeffdill2    5 年前

    下面是一个解决方案,通过使用 extend

    module SomeModule
    
      class ClassThatDoesNotExtendTheModule
        class << self
          def random_class_method
            private_class_on_module
          end
        end
      end
    
      class ClassThatDoesExtendTheModule
        extend SomeModule
      
        class << self
          def random_class_method
            private_class_on_module
          end
        end
      end
    
      class AnotherClassThatDoesExtendTheModule
        extend SomeModule
      
        class << self
          def random_class_method
            private_class_on_module
          end
        end
      end
    
      private
    
      def private_class_on_module
        puts 'some private class was called'
      end
      
    end
    
    

    > SomeModule::ClassThatDoesNotExtendTheModule.random_class_method
    
    NameError: undefined local variable or method `private_class_on_module' for SomeModule::ClassThatDoesNotExtendTheModule:Class
    
    
    > SomeModule::ClassThatDoesExtendTheModule.random_class_method
    
    some private class was called
    
    
    > SomeModule::ClassThatDoesExtendTheModule.private_class_on_module
    
    NoMethodError: private method `private_class_on_module' called for SomeModule::ClassThatDoesExtendTheModule:Class
    
    
    > SomeModule::AnotherClassThatDoesExtendTheModule.random_class_method
    
    some private class was called
    
    
    > SomeModule::AnotherClassThatDoesExtendTheModule.random_class_method
    
    NoMethodError: private method `private_class_on_module' called for SomeModule::AnotherClassThatDoesExtendTheModule:Class