문제

이것 말고도 self.class.send :method, args..., 물론.코드를 복제하지 않고 클래스와 인스턴스 수준 모두에서 사용할 수 있는 다소 복잡한 메서드를 만들고 싶습니다.


업데이트:

@조나단 브래넘:그것은 내 가정이었지만, 다른 누구도 방법을 찾지 못했음을 확인하고 싶었습니다.Ruby의 가시성은 Java의 가시성과 매우 다릅니다.당신 말이 정말 맞아요 private 클래스 메소드에서는 작동하지 않지만 비공개 클래스 메소드를 선언합니다.

class Foo
  class <<self
    private
    def bar
      puts 'bar'
    end
  end
end

Foo.bar
# => NoMethodError: private method 'bar' called for Foo:Class
도움이 되었습니까?

해결책

다음은 질문과 관련된 코드 조각입니다.클래스 정의에서 "private"을 사용하는 것은 클래스 메서드에 적용되지 않습니다.다음 예시와 같이 "private_class_method"를 사용해야 합니다.

class Foo
  def self.private_bar
    # Complex logic goes here
    puts "hi"
  end
  private_class_method :private_bar
  class <<self
    private
    def another_private_bar
      puts "bar"
    end
  end
  public
  def instance_bar
    self.class.private_bar
  end
  def instance_bar2
    self.class.another_private_bar
  end
end

f=Foo.new
f=instance_bar # NoMethodError: private method `private_bar' called for Foo:Class
f=instance_bar2 # NoMethodError: private method `another_private_bar' called for Foo:Class

이 문제를 해결할 방법이 없습니다.설명서에는 개인 메서드의 수신을 지정할 수 없다고 나와 있습니다.또한 동일한 인스턴스에서만 비공개 메서드에 액세스할 수 있습니다.Foo 클래스는 Foo의 특정 인스턴스와 다른 개체입니다.

내 대답을 최종적인 것으로 받아들이지 마십시오.저는 확실히 전문가는 아니지만 답변을 시도하는 다른 사람들이 적절한 비공개 클래스 메소드를 가질 수 있도록 코드 조각을 제공하고 싶었습니다.

다른 팁

다소 이상한 솔루션과 비 솔루션 목록에 기여하겠습니다.

puts RUBY_VERSION # => 2.1.2

class C
  class << self
    private def foo
      'Je suis foo'
    end
  end

  private define_method :foo, &method(:foo)

  def bar
    foo
  end
end

puts C.new.bar # => Je suis foo
puts C.new.foo # => NoMethodError

귀하의 방법이 단지 유틸리티 기능 (즉, 인스턴스 변수에 의존하지 않습니다.) 메소드를 모듈에 넣고 include 그리고 extend 프라이빗 클래스 메서드와 프라이빗 인스턴스 메서드 모두로 사용할 수 있도록 클래스를 생성합니다.

요즘에는 더 이상 도우미 메서드가 필요하지 않습니다.메소드 정의를 사용하여 간단히 인라인할 수 있습니다.이는 Java 사용자에게 매우 친숙하게 느껴질 것입니다.

class MyClass

  private_class_method def self.my_private_method
    puts "private class method"
  end

  private def my_private_method
    puts "private instance method"
  end

end

그리고 아니요, 인스턴스 메서드에서 개인 클래스 메서드를 호출할 수 없습니다.그러나 대신 다음을 구현할 수 있습니다. 사적인 클래스 메소드 공공의 클래스 메소드 사적인 대신 중첩 클래스를 사용하여 private_constant 도우미 방법.보다 이 블로그 게시물 자세한 내용은.

이것이 "실제" 비공개 클래스 메서드를 사용하는 방법입니다.

class Foo
  def self.private_bar
    # Complex logic goes here
    puts "hi"
  end
  private_class_method :private_bar
  class <<self
    private
    def another_private_bar
      puts "bar"
    end
  end
  public
  def instance_bar
    self.class.private_bar
  end
  def instance_bar2
    self.class.another_private_bar
  end
  def calling_private_method
    Foo.send :another_private_bar
    self.class.send :private_bar
  end
end
f=Foo.new
f.send :calling_private_method 
 # "bar"
 # "hi"
Foo.send :another_private_bar
# "bar"

건배

이것은 아마도 가장 "네이티브 바닐라 Ruby" 방식일 것입니다:

class Foo
  module PrivateStatic # like Java
    private def foo
      'foo'
    end
  end
  extend PrivateStatic
  include PrivateStatic

  def self.static_public_call
    "static public #{foo}"
  end

  def public_call
    "instance public #{foo}"
  end
end

Foo.static_public_call # 'static public foo'
Foo.new.public_call # 'instance public foo'
Foo.foo # NoMethodError: private method `foo' called for Foo:Class
Foo.new.foo # NoMethodError: private method `foo' called for #<Foo:0x00007fa154d13f10>

일부 Ruby 메타프로그래밍을 사용하면 다음과 같이 만들 수도 있습니다.

class Foo
  def self.foo
    'foo'
  end

  extend PrivateStatic
  private_static :foo
end

Ruby의 메타프로그래밍은 매우 강력하므로 원하는 범위 지정 규칙을 기술적으로 구현할 수 있습니다.그럼에도 불구하고 나는 여전히 명확성과 최소한의 놀라움 첫 번째 변종 중.

내가 오해하지 않는 한 다음과 같은 것이 필요하지 않습니까?

class Foo
    private
    def Foo.bar
        # Complex logic goes here
        puts "hi"
    end

    public
    def bar
        Foo.bar
    end
end

물론 클래스 이름을 하드코딩하지 않으려면 self.class.send 접근 방식을 사용하도록 두 번째 정의를 변경할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top