評價: 2 回應: 2 閱覽: 109
置頂

關於類別方法 attr_reader

你們好

我想請問,在ruby裡面的attr_reader ..等方法

如以下範例:
 

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

為何定義 attr_accessor時,會知道 :name 這個變數是指向 實例變數@name呢?

如果在類別裡面定義了其他變數,如類別變數,全域變數 等

attr_accessor還會知道是指向@name嗎?


還是在ruby裡面,存取器一定就是預設是實例變數?

謝謝你們了,查了資料還是不太懂..

熱門回應

Ruby 當中,如果定義了 attr_accessor :name 的話,會產生兩個 method

    def name
      @name
    end

    def name=(name)
      @name = name
    end

所以除非你去覆寫這兩個 method ,否則 name 之後都等於呼叫 name

這個 method然後 return @name

所以除了 initialze 之外,name 都可以直接取代 @name

 

取代 @name 的好處在於,如果有時候你需要對資料本身做一些處理

想要 output處理後的數據,可以直接修改 method 就好

舉例來說,今天你要顯示電話

可是不想顯示出電話的最後三碼,你可以直接做:

   attr_reader :mobile

   def mobile

# 假設電話號碼是 0922-123-345
   split_num = @mobile.split("-")
   split_num[2] = "XXX"
   @mobile =  split_num.join("-")
   end

當你 call mobile 的時候,它顯示的就會是 0922-123-XXX 而非原本的號碼

 

另外一點要注意的是,當你使用 attr_accessor 或是 attr_writer 的時候

雖然你可以用 name 來取代 @name ,但是當你創造一個新的 method

想要使用 setter 的時候,例如:

   def get_name
   # 原本可能是 @name = gets.chomp
   # name = gets.chomp 不行
   self.name = gets.chomp
   end

   你如果不用 @name 的話,前面必須要加一個 self

原因在於如果你沒加 self 的話,他會認為你是在 get_name 裡面設一個 local variable

就無法 pass 到該物件的name 去

Ruby可以動態定義方法

其實使用屬性存取也是定義方法

可以想像成

eval("def #{sym}=(val);@#{sym}=val;end")

eval("def #{sym});return @#{sym};end")

上面寫這行讀在attr_accessor中會定義name和name=(val)

會員登入 (先登入會員才能回覆留言喔!)

Facebook留言