在最近的練習中,只有印象自己大量的在用attr_reader :somthing
,在完成這篇文章前,我完全不知道其實它就是getter method...
關於setter就真的更陌生了,也有在專案或練習的時候有用到,但也一樣完全不知道其實在用的就是setter method,所以決定寫個一篇文章來釐清一下觀念。
Ruby沒有屬性這件事,跟其他程式語言不一樣,下面的例子:
my.event
#其實原型是
my.event()
my.event = "something"
#其實原型是
my.event=("something")
my.event看起來像是在my上讀取event的屬性,但它實際是執行了my.event()方法,只是括號可以適時省略,相同的my.event=("something")也是同樣道理。
就英文直翻getter method是「取得(get)的方法」的意思,在Ruby裡指的就是取出實體變數(instance variable)的方法。
如果class裡沒有getter method,就無法取出在class內實體變數的值。
class Favorite
def initialize(event)
@event = event
end
end
my = Favorite.new('Badminton')
puts my.event
會印出錯誤訊息
undefined local variable or method `badminton' for main:Object (NameError)
可以看得出來,my這個實體拿不到class裡的實體變數@event,如果要拿到@event的話,必須給它一個getter method。
class Favorite
def initialize(event)
@event = event
end
def event #getter method
@event
end
end
my = Favorite.new('Badminton')
puts my.event # => Badminton
龍哥說,工程師都很懶惰,如果每次要取實體變數的值都要寫一次getter method不是很麻煩嗎?
class Favorite
attr_reader :event
def initialize(event)
@event = event
end
# def event #getter method
# @event
# end
end
my = Favorite.new 'Badminton'
puts my.event
在class內加入 attr_reader :event
就自動幫你產生寫了第8~10行。
就英文直翻setter method是「指派(assign)的方法」的意思,在Ruby裡指的就是指派實體變數(instance variable)的方法。
如果class裡沒有setter method,就無法派在class內實體變數的值。
class Favorite
attr_reader :event
def initialize(event)
@event = event
end
# def event #getter method
# @event
# end
end
my = Favorite.new('Badminton')
puts my.event # => Badminton
puts my.event = "Pasta"
會印出錯誤訊息
undefined local variable or method `badminton' for main:Object (NameError)
可以看得出來,my這個實體做event方法時,如果要直接指派event方法內部的實體變數@event為"Pasta",必須給它一個setter method。
class Favorite
attr_reader :event
def initialize(event)
@event = event
end
# def event #getter method
# @event
# end
def event= food #setter method
@event = food
end
end
my = Favorite.new('Badminton')
puts my.event # => Badminton
puts my.event=("Pasta") # => Pasta
等等....為什麼方法名稱有個等於又帶括號?
Rub6定義方法時,等號跟其他字元都可以當作是名字的一部分,只是規定上必須放在最後面。
所以可以將event=(food)
解讀一下:event= 是方法名稱,帶有參數food
event=(food)
#括號可適時的省略
event=food
#可適時加入空白字元
event = food
class Favorite
attr_reader :event
def initialize(event)
@event = event
end
# def event #getter method
# @event
# end
def event= food #括號可適時的省略 #setter method
@event = food
end
end
my = Favorite.new('Badminton')
puts my.event # => Badminton
puts my.event = "Pasta" # => Pasta #括號可適時的省略並加入空白字元
還好工程師都很懶惰再一次,這裏也可以寫成attr的方式。
class Favorite
attr_reader :event
attr_writer :event
def initialize(event)
@event = event
end
# def event #getter method
# @event
# end
# def event= food #setter method
# @event = food
# end
end
my = Favorite.new('Badminton')
puts my.event # => Badminton
puts my.event = "Pasta" # => Pasta
在class內加入attr_writer :event
就自動幫你產生寫了第13~15行。
還好偉大的懶惰工程師們,覺得如果要再多個實體變數的話,就得要再寫attr_reader
跟attr_writer
的方式來取得跟指派,實在太麻煩了...
class Favorite
# attr_reader :event
# attr_writer :event
# attr_reader :price
# attr_writer :price
attr_accessor :event, :price
def initialize(event, price)
@event = event
@price = price
end
# def event #getter method
# @event
# end
# def event= food #setter method
# @event = food
# end
end
my = Favorite.new('Badminton', "$200")
my.event = "Volleyball"
my.price = "$300"
puts my.event # => Volleyball
puts my.price # => $300
在class內加入attr_accessor :event, :price
就自動幫你產生寫了第2~5行。
這也是為何我們在rails專案裡,可以用點的方式取值的概念,例如:第5~10行,在rails裡的Active Record(MVC的M (Model)),會自動建立attr_accessor :foods
。
<% @foods.each do |food| %>
<ul>
<li>
名稱:<%= food.title%>
數量:<%= food.quantity%>
可領取時間:<%= food.pickup_time%>
原價:<%= food.origin_price%>
救援價:<%= food.discount_price%>
描述:<%= food.description%>
</li>
</ul>
<%end%>
attr_reader
+ attr_writer
= attr_accessor
參考資料:
How getter/setter methods work in Ruby
Ruby Getters and Setters
Ruby 語法放大鏡之「attr_accessor 是幹嘛的?
“The conditions of conquest are always easy. We have but to toil awhile, endure awhile, believe always, and never turn back.”
— Lucius Annaeus Seneca, Philosopher
本文同步發佈於: https://louiswuyj.tw/