關於類別方法 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)