2011-04-24 51 views
1

在Ruby中,有沒有辦法做這樣的事情有沒有辦法讓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 2011-04-24 19:07:08

+1

當您的內部名稱與外部接口規格不同時。這出現在about_dice_project ruby​​-koan上。他們想要調用最近形成的「擲骰子」列表。我想叫它'@ lastRolled'。一個是指它被實現的方式(作爲一個內部變量應該),另一個是指定者對它的思考方式。在這種情況下,這並不重要,但我可以看到這是我未來可能想知道的事情。 – Eponymous 2011-04-24 19:45:22

+0

upvote for well written Q.我不需要喜歡你的要求;) – oma 2011-04-24 21:03:10

回答

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方法仍然是可用的,但。你可以使用remove_method擺脫var_name方法,如果你真的想要的(但要確保你得到正確的順序一切):

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

如果你真的想,你可以猴子打補丁的attr_reader_as方法成模塊:

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

你不能傳遞任何選項attr_reader

這是一個handcoding?

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

+1爲「不要那麼懶惰,自己動手」。對不起,破壞你的酷8888的聲望。 – 2011-04-24 19:15:18

+0

是的,這是一個手工編碼。但是你的回答讓我知道,大多數ruby程序員可能會這樣做。當然,[懶惰是美德](http://c2.com/cgi/wiki?LazinessImpatienceHubris)。 – Eponymous 2011-04-24 19:54:40

2

首先,我的口頭禪:一個好的程序員能夠很好地扮演他的隊友。按照慣例打好別人。

你想要的東西看起來非常規,而@gergerunner指出,不好的做法(讀:我會打你)。我只是說,想想這個,我不知道你的用例,它可能證明是有效的......無論如何,在復活節期間應該允許有點樂趣,所以我練習了一些元編程,並與Mixins一起玩。

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

很乾淨。該模塊的伎倆(請務必在上課前加載該模塊)

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 

測試在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> 

我希望你看到直觀的,這將是爲別人着想。您可以覆蓋to_s方法來顯示如何訪問@var_name,但我不會去那裏......或者也定義var_name方法(兩個getter方法)。堅持約定。無論如何,我很開心,祝你好運!

相關問題