2011-04-24 6 views
1

, 즉attr_reader가 인스턴스 변수와 다른 이름으로 메소드를 만들 수있는 방법이 있습니까? 루비에서

class Foo 
    attr_reader :var_name :reader_name #This won't work, of course 
    def initialize 
     @var_name = 0 
    end 
end 

# stuff here .... 

def my_method 
    foo = Foo.new 
    assert_equal 0,foo.reader_name 
end 

같은 것을 할 수있는 방법이 변수가 아닌 다른 이름을 사용하는 변수에 대한 접근 방법을 만들 수있는 표준 방법이있다. (물론, 그것을 handcoding 게다가.)

+1

왜 그렇게하고 싶습니까? 아마도 나쁜 습관 일 것입니다. – edgerunner

+1

내부 이름이 외부 인터페이스 사양과 다른 경우. 이것은 about_dice_project ruby-koan에서 작업하기 시작했습니다. 가장 최근에 형성된 '주사위 주사위 목록'을 '가치'라고 부르기를 원합니다. '@ lastRolled'라고하고 싶습니다. 하나는 구현 된 방법 (내부 변수로서)이고 다른 하나는 지정자가 그것에 대해 생각하는 방식을 나타냅니다. 이 경우 조금 문제가되지 않지만 앞으로 알게 될 수있는 내용임을 알 수 있습니다. – Eponymous

+0

잘 쓰여진 Q를위한 upvote Q. 나는 당신이 요구하는 것을 좋아할 필요가 없다.) – oma

답변

3

당신은 alias_method을 사용할 수

class Foo 
    attr_reader :var_name 
    alias_method :reader_name, :var_name 
    def initialize 
     @var_name = 0 
    end 
end 

attr_reader에 의해 내장 var_name 방법은 여전히 ​​있지만 사용할 수있다. 당신은 당신이 정말로 원하는 경우 var_name 방법 없애 remove_method를 사용 (하지만 당신이 올바른 순서로 모든 것을 얻을 수 있는지 확인) 수 : 당신이 정말로, 당신은 원숭이 내로 attr_reader_as 방법을 패치 할 수 싶었다면

class Foo 
    attr_reader :var_name 
    alias_method :reader_name, :var_name 
    remove_method :var_name 
    def initialize 
     @var_name = 0 
    end 
end 

을 모듈 :

class Module 
    def attr_reader_as(attr_name, alias_name) 
     attr_reader attr_name 
     alias_method alias_name, attr_name 
     remove_method attr_name 
    end 
end 

class Foo 
    attr_reader_as :var_name, :reader_name 
    def initialize 
     @var_name = 0 
    end 
end 

더 나은 attr_reader_as 해시 (예 : {:var_name => :reader_name, :var_name2 => :reader_name2}) 걸릴 것이다 그러나 나는 독자들에게 운동으로 떠날 것이다.

4

당신은 어떤 옵션

이것은 handcoding인가를 attr_reader을 전달할 수 없습니다?

class Foo 
    def initialize 
     @var_name = 0 
    end 
    def reader_name; @var_name; end 
end 
+1

+1 "너무 게으르지 말고 스스로해라". 시원하고 운이 좋은 8888 평판을 붕괴해서 죄송합니다. –

+0

예, 직접 코딩하는 것입니다. 그러나 여러분의 반응은 루비 프로그래머가 그렇게 할 가능성이 높다는 것을 알려줍니다. [게으름은 미덕이다] (http://c2.com/cgi/wiki?LazinessImpatienceHubris) 물론. – Eponymous

2

우선, 내 mantra : 좋은 프로그래머가 팀 동료를 잘합니다. 관습에 따라 다른 사람들을 잘 보살펴야합니다.

당신이 원하는 것은 틀에 얽매이지 않는 것처럼 보입니다. @edgerunner가 말하듯이, 나쁜 습관 (읽기 : 나는 당신을 때리겠다)입니다. 내가 말하는 건, 이것에 대해 두 번 생각하고, 당신의 유스 케이스를 알지 못한다면, 그것은 유효 할 것입니다. 어쨌든, 부활절 동안의 약간의 재미는 허용되어야합니다. 그래서 나는 약간의 메타 프로그래밍을 연습하고 Mixins로 연주했습니다.

class Foo 
    include MyAttrReader 
    my_attr_reader :var_name, :reader_name 
    def initialize 
    @var_name = 0 
    end 
end 

매우 깨끗합니다. 이 모듈은 IRB

ruby-1.9.2-p180 :001 > load 'my_attr_reader.rb' 
=> true 
ruby-1.9.2-p180 :002 > load 'foo.rb' 
=> true 
ruby-1.9.2-p180 :003 > f = Foo.new 
=> #<Foo:0x00000100979658 @var_name=0> 
ruby-1.9.2-p180 :004 > f.reader_name 
=> 0 
ruby-1.9.2-p180 :005 > f.var_name 
NoMethodError: undefined method `var_name' for #<Foo:0x00000100979658 @var_name=0> 

난 당신이 다른 사람을 위해 얼마나 직관적 볼 희망의 트릭 (클래스 전에이 모듈을로드해야합니다)

module MyAttrReader 
    def self.included(base) 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def my_attr_reader(attribute, read_attribute) 
     define_method "#{read_attribute}" do 
     instance_variable_get "@#{attribute}" 
     end 
    end 
    end 
end 

테스트를 수행합니다. @var_name에 액세스하는 방법을 보여주기 위해 to_s 메서드를 재정의 할 수 있지만 거기에 가지 않거나 ... var_name 메서드도 정의합니다 (두 getter-methods). 협약에 충실하십시오. 어쨌든, 나는 재밌어, 행운을 빌어!