2012-12-08 4 views
0

내 프로젝트 에는이 클래스가 Foo인데이 인스턴스는 고유하고 이름이 지정된 실제 개체를 나타냅니다. 이 인스턴스에 대한 참조는 프로젝트의 데이터 구조를 중심으로 잘 관리되어 있지만 이름으로 액세스 할 수 있도록하기로 결정했습니다. 이를 위해 Foo 클래스 자체가 인스턴스를 추적합니다 (예 :클래스가 다른 클래스의 개인 클래스 메서드 또는 동등한 솔루션을 선택적으로 사용할 수 있도록 허용

).
module Bar 
    class Foo 
    attr_reader :name 

    def initialize(name) 
     @name = name 
    end 

    def self.new *args, &block 
     new_instance = super 
     n_i_name = new_instance.name 
     (@instances ||= {}).merge! new_instance => n_i_name 
     return new_instance 
    end 

    def inspect; "Foo instance #{name}" end 
    end 
end 

이제 이것은 일반적인 패턴입니다. 일반적으로, 인스턴스에 액세스 할 일이 Foo의 공용 클래스 메소드를 설정할 수 있습니다 :

class << Bar::Foo 
    def instance(i) 
    case i 
    when self then i 
    else @instances.rassoc(i).first end 
    end 
end 

i = Bar::Foo.new "John Smith" 
#=> Foo instance John Smith 
i.object_id 
#=> 68997470 
Bar::Foo.instance("John Smith").object_id 
#=> 68997470 

그러나 문제는 이러한 Bar::Baz, Bar::Quux 등으로 Bar 모듈에서 명명 된 인스턴스와 유비 클래스가 있다는 것을, Foo 인스턴스에 액세스하고 이름별로 서로 액세스해야합니다. 그래서 나는이 다양한 클래스의 이름으로 서로의 인스턴스에 액세스하는 방식에 질서를 유지 Bar 모듈 자체의 책임이라고 생각하고, 나는 그것이 공공 모듈 방법 작성 : 클래스 Foo, Baz는, Quux가 참조 할 때마다

module Bar 
    # Foo method blah blah blah... 
    def self.Foo(i); Foo.instance i end 

    # Baz method blah blah blah... 
    def self.Baz(i); Baz.instance i end 

    # Quux method blah blah blah... 
    def self.Quux(i); Quux.instance i end 
end 

을 서로에게 Bar.Foo("John Smith") 스타일 호출을 사용하면 이러한 인스턴스를 고유 한 이름으로 참조 할 수도 있습니다. 이제 내 문제는 이것이 여전히 나에게 100 % 정결 한 것처럼 보이지 않는다는 것이다. rdoc을 실행하여 Bar 모듈의 설명서를 만들 때 공용 클래스 메서드 #Foo, #Baz, #Quux을 문서화하십시오. 그러나 이것들은 실제로 사용자 인터페이스의 일부가되는 것은 아닙니다. 그래서 문제가 각각 다음과 같은 옵션이 있습니다

  1. 가 포함를 #Foo, 사용자 인터페이스의 #Baz, #Quux. 문제 : 사용자가 실제로 그렇게 나쁘지는 않습니다. 그것들을 UI에 가지고있는 것이 나의 의도는 아니었다.

  2. rdoc이 문서화되지 않도록하기 위해 # :nodoc: 지시문을 추가하십시오. 문제 : 기분이 좋지 않습니다. Bar.Foo이 아니며 친구가 사용자 인터페이스에서 제외되었습니다. 그것은 여전히 ​​UI의 일부분 인 것처럼 느껴지지만 문서화되지 않은 비밀입니다. 나는 그것을 원하지 않는다.

  3. #private_class_method을 사용하여 비공개로 선언하십시오. 그런데, 심지어 경우에도 #Foo, #Baz, #Quux 일반적인 작업 중에 이름으로 서로 액세스, 그들도 역시 Bar.send :Foo, "John Smith" 스타일을 사용해야합니다.

질문 : 옵션 3은 가장 해로운 것 같습니다. 하지만 여전히 완벽하지는 않습니다. 이상적으로는 Bar.Foo, Bar.Baz, Bar.Quux 등의 방법으로 보호하고 싶습니다. 사용자가 Bar.send :Foo, "John Smith"을 사용해야하지만이 사람들은 Bar.Foo "John Smith"을 호출하여 서로를 호출 할 수 있으며 이러한 모듈 방법은 사용자를 위해 문서화되어 있지 않은 것이 좋습니다. . 어떤 다른 옵션이 있다면,이 상태를 달성해야합니까? 일부 클래스가 임의로 다른 사람의 개인 메소드를 사용하도록 선택적으로 허용하는 방법이 있습니까? 또한, 나는 보호 된 클래스 메서드에 대한 경험이 없다. 해결책 일 수 있을까? 이것을 읽은 시간을 가져 주셔서 감사합니다.

답변

1

개인 정보 보호를 위해 Understanding private methods in Ruby을보고 SO를 검색하십시오. 읽을 자료가 많이 있습니다.

보호 된 클래스 메소드 :

class Foo 
    class << self 
     def prot 
      puts "self.prot" 
     end 
     protected :prot 
    end 
... 

Bar::Foo.prot #=> protected method `prot' called for Bar::Foo:Class (NoMethodError) 
+0

멋진 대답,하지만 sligthly 다른 질문. Btw. 보호 된 클래스 메소드와 같은 것이 있습니까? –

+0

위의 내용 (편집 기능이 충분하지 않음)을 이해하는 것이 더 어려워 보입니다. – user1852994

+0

"Foo, Baz, Quux 클래스가 서로 참조"하는 예제를 제공 할 수 있습니까? 왜 세 가지 모두 인스턴스를 가져 오는 다른 액세스 방법이 있습니까? 수퍼 클래스의 모든 인스턴스/명명 메커니즘을 제외하지 않으시겠습니까? – user1852994