IT

Ruby의 비공개 모듈 메소드

lottoking 2020. 8. 21. 08:01
반응형

Ruby의 비공개 모듈 메소드


두 부분으로 된 질문이 있습니다.

모범 사례

  • 공용 인터페이스를 사용하여 데이터 구조에서 일부 작업을 수행하는 알고리즘이 있습니다.
  • 현재 하나의 공용 인터페이스 메소드를 제외하고 모두 전용 인 수많은 정적 메소드가있는 모듈입니다.
  • 모든 메소드간에 공유해야하는 인스턴스 변수가 하나 있습니다.

다음은 내가 볼 수있는 옵션이며 가장 좋은 것은 무엇입니까? :

  • 모듈 정적 (루비 '모듈')와 방법
  • 정적 메서드가있는 클래스
  • 데이터 구조에 포함하기위한 Mixin 모듈
  • 해당 데이터 구조 (매우 작음)를 수정하는 알고리즘 부분을 리팩터링 하고 알고리즘 모듈의 정적 메소드를 호출하는 믹스 인으로 만듭니다.

기술 부분

private Module 방법을 만드는 방법이 있습니까?

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

private거기에는 어떤 영향을 미칠 것 같지 문제 난 여전히 호출 할 수 있습니다 Thing.priv.


나는 모든 것이되는 편리한 다루는 모듈 내에서 클래스를 만드는 것이 최선의 방법 (그리고 대부분의 기존 라이브러리가 작성 방법)이라고 생각하며, 모듈은 단지 방법을 제공합니다.

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더 많은 의도를 표현했습니다.

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

"포함"메서드를 사용하여 모듈이 혼합 될 때 멋진 작업을 수행 할 수 있습니다. 이 원하는대로 수행합니다.

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


불행히도 인스턴스 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에서이 작업을 통해 찾은 최고의 패턴은 private 메서드를 갖고 싶은 모듈을 포기하고 대신 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

클래스 변수 / 상수 내에 메서드를 람다로 저장하는 것은 무엇입니까?

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

테스트 용 :
UPD : 6 년 후이 코드를 대대적으로 업데이트하면 private 메서드를보다 깔끔하게 선언 할 수 있습니다.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방법은 비공개로하지 않습니다 - 그들은 액세스 할 수있는 두 유무에 관계없이self.


개인 모듈 또는 클래스 만들기

상수는 결코 비공개가 아닙니다. 그러나 상수에 할당하지 않고 모듈이나 클래스를 만들 수 있습니다.

따라서 대안 :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.newClass.new 문서를 참조하십시오 .

참고 URL : https://stackoverflow.com/questions/318850/private-module-methods-in-ruby

반응형