iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 11
0
自我挑戰組

非本科之30天Ruby / Rails學習筆記系列 第 11

Day11: Ruby中的Getter及Setter?

  • 分享至 

  • xImage
  •  

在最近的練習中,只有印象自己大量的在用attr_reader :somthing,在完成這篇文章前,我完全不知道其實它就是getter method...

關於setter就真的更陌生了,也有在專案或練習的時候有用到,但也一樣完全不知道其實在用的就是setter method,所以決定寫個一篇文章來釐清一下觀念。

Ruby沒有「屬性(property/attribute)」

Ruby沒有屬性這件事,跟其他程式語言不一樣,下面的例子:

my.event
#其實原型是
my.event()

my.event = "something"
#其實原型是
my.event=("something")

my.event看起來像是在my上讀取event的屬性,但它實際是執行了my.event()方法,只是括號可以適時省略,相同的my.event=("something")也是同樣道理。

什麼是getter method?

就英文直翻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不是很麻煩嗎?

attr_reader

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?

就英文直翻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

等等....為什麼方法名稱有個等於又帶括號?

Ruby魔法糖? - 括號可適時的省略

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的方式。

attr_writer

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_readerattr_writer的方式來取得跟指派,實在太麻煩了...

attr_accessor

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%>

總結

  1. getter method: 取出實體變數(instance variable)的方法。
  2. setter method: 指派實體變數(instance variable)的方法。
  3. 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/


上一篇
Day10: Ruby中的Conditional Assignment Operator: x ||= y(or-equals)
下一篇
Day12: Ruby的例外處理(Exceptions):begin...rescue ...end
系列文
非本科之30天Ruby / Rails學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言