2010-08-02 13 views
2
class Foo 
    def initialize 
    @bar = [] 
    end 

    def changed_callback 
    puts "Bar has been changed!" 
    end 

    def bar 
    @bar 
    end 

    def bar=(a) 
    @bar = a 
    self.changed_callback() # (hence why this doesn't just use attr_accessor) 
    end 

    def bar<<(a) 
    @bar.push(a) 
    self.changed_callback() 
    end 
end 

f = Foo.new() 
f.bar = [1,2,3] 
    => "Bar has been changed!" 
f.bar << 4 
    => "Bar has been changed!" 
puts f.bar.inspect 
    => [1,2,3,4] 

그렇게 할 수 있나요?맞춤 << 방법

감사합니다.

+0

'bar'는 간단한 배열이 아닌 다른 것을 반환 할 필요가 있다고 생각합니다. 그렇다면'x = f.bar' 다음에'x << 4'를 어떻게 붙잡아 두겠습니까? 그래서'bar'는 소유 객체에 대한 참조를 가진 array의 서브 클래스를 리턴하고 소유자에 대해'changed_callback' 메소드를 호출하기 위해'<<'를 오버라이드해야합니다 (그러나'x = f.bar; f.bar = []; x 이 경우에 콜백을 원한다면 "4"는 처리하기가 더 까다 롭습니다 -'f'는 모든'x'에 대해 알고 있어야하고 새로운'bar'가 전달 될 때 "비활성화"합니다. 'changed_callback'가 호출자를 arg로 받아 들여서'f'가 검사 할 수 있도록해야합니다 ... –

+0

아! 어떤 이유로 attr_accessor가 막 대형을 만들었습니다. 고맙습니다! (답변으로 의견을 게시하여 해결할 수 있도록 표시하고 싶습니까?) –

+0

이 스택 교환 [제안] (http://area51.stackexchange.com/proposals/11464/code-review?referrer=aWNm_PdciyFqjFW8CUacGw2 "코드 검토")가 도움이 될 수 있습니다. 귀하의 지원을 나타내고 베타 테스트에 도움이되는 경우 – greatwolf

답변

3

Foo#bar에 의해 반환 된 객체를 어떤 방법 으로든 #<< 메서드로 확장해야합니다. 이게 뭔가?

class Foo 
    module ArrayProxy 
    def <<(other) 
     @__foo__.changed_callback 
     super 
    end 
    end 

    def initialize 
    @bar = [] 
    end 

    def changed_callback 
    puts 'Bar has been changed!' 
    end 

    def bar 
    return @bar if @bar.is_a?(ArrayProxy) 
    @bar.tap {|bar| bar.extend(ArrayProxy).instance_variable_set(:@__foo__, self) } 
    end 

    def bar=(a) 
    @bar = a 
    changed_callback # (hence why this doesn't just use attr_accessor) 
    end 

end 

f = Foo.new 
f.bar = [1,2,3] 
# "Bar has been changed!" 
f.bar << 4 
# "Bar has been changed!" 
puts f.bar.inspect 
# => [1,2,3,4]