2013-10-28 5 views
0

클래스 속성 목록을 별도의 메서드 또는 상수로 정의하면 코드에서 여러 번 사용할 수 있습니다. A)attr_accessor 호출 (세터와 게터의 무리)의 결과에서 속성의 목록을 검색 어렵다; 때문에부모 클래스의 자식 메서드를 사용하여 attr_accessor를 호출하십시오.

attr_accessor :a, :b, :c 

는 일을하지 않습니다 b) 내 특성 목록에 일부 메타 데이터를 넣어야합니다. 리스트를 상수로 옮기는 것은 일을합니다. 왜냐하면 이제 목록으로 원하는 것을 할 수 있고 여전히 심볼 배열을 attr_accessor에 전달할 수 있기 때문입니다. 예컨대 :

class A 
    FIELDS = {a:'field a', b:'field b'} 

    def self.field_names 
    FIELDS.keys 
    end 

    attr_accessor *field_names 
end 

하지만 그래서 부모 클래스에 self.field_namesattr_accessor *field_names 같은 모든 반복 코드를 이동해야 DRY를 유지하기 위해, 유사한 종류의 많은이하고 싶어. 하지만 이것은 작동하지 않습니다.

class A 
    FIELDS = {a:'field a', b:'field b'} 

    def self.field_names 
    FIELDS.keys 
    end 

    attr_accessor *field_names 
end 

class B < A 
    FIELDS = {c: 'field c'} 
end 

attr_accessor은 여전히 ​​A의 방법을 사용하기 때문에 작동하지 않습니다. 코어 Class을 사용하지 않고이 작업을 수행 할 수 있습니까?

부모 클래스에서 자식 클래스의 메서드를 사용하여 attr_accessor를 호출 할 수있는 방법이 있습니까?

답변

2

코드 A을로드 할 때 attr_accessor이 여전히 부득이하게 호출되기 때문에 코드가 작동하지 않습니다. 이 시점에서 클래스 B은 아직 (완전히) 존재하지 않으므로 상수를 변경할 수 없습니다.

예를 들어 실제 인스턴스가 만들어 질 때까지 인스턴스 메서드 생성을 지연 할 수 있습니다 (이 솔루션을 너무 좋아하지는 않습니다).

class A 
    FIELDS = {a:'field a', b:'field b'} 

    def initialize 
    self.class.class_eval do 
     attr_accessor *field_names 
    end 
    end 

    def self.field_names 
    self.const_get(:FIELDS).keys 
    end 

end 

class B < A 
    FIELDS = {c: 'field c'} 
end 

b = B.new 
b.methods() # => [:c, :c=, ... 
+0

위대한! 정확히 내가 원했던 것. 감사 세르지오! – Hnatt

+0

잠깐,이 솔루션에 대해 나쁘다. 어떤 대안이 있을까요? – Hnatt

+0

아마도 이니셜 라이저 대신'attr_accessor * field_names' 라인을 FIELDS 라인 바로 뒤의 B로 옮길 수 있습니까? 그런 식으로 각 하위 클래스는 접근자를 한 번만 정의 할 것이고 여전히 하위 클래스 별 필드를 사용하게됩니까? –

관련 문제