iT邦幫忙

DAY 19
1

Ruby女孩:10萬.times { puts "為什麼?" }系列 第 19

Ruby女孩(19):類別中的getter與setter

昨天我們開頭引入了書中的一段話,其中提到了取得器(getter)、設定器(setter)、存取器方法(accessor method)等等,今天會來把這個部分的觀念給弄清楚些!

還記得昨天的例子嗎?我們做了一個名字為RubyGirl的類別,類別中我們給了一個初始化的方法,與一個年齡的方法,如下:

class RubyGirl
  def initialize(ruby_skill=0)
    @ruby_skill = ruby_skill
  end

  def age
    @a
  end
end

現在對這個類別我們可以已經可以創出一個實例,而且有初始值@rubyskill=0:

annie = RubyGirl.new
=> #<RubyGirl:0x007fe5623936c8 @ruby_skill=0>

而且也有一個年齡的方法:

annie.age
=> nil

但是當我們想要**改變年齡的值**時,它會噴NoMethodError的錯,例如:

annie.age = 25
NoMethodError: undefined method `age=' for #<RubyGirl:0x007fe5623936c8 @ruby_skill=0, @a=nil>

這時候,我們就要來說說gettersetter了!

目前我們在類別中所定義的年齡,只是@a的getter方法如果我們需要@a具有可變性,那我們就得再加上一個setter的方法,如下說明:

class RubyGirl
  # @a的getter方法
  def age
    @a
  end
  # @a的setter方法
  def age=(x)
    @a = x
  end
end

有了setter方法後,我們就可以讓年齡具有改變性:

annie.age
=> nil
#能得到初始值,是因為我們有定義一個age方法。

annie.age=20
=> 20
#能改變age,是因為我們有定義一個age=方法。

由於這一對getter和setter的方法極為常見,所以Ruby提供了一個自動化的做法:Module定義了attr_reader與attr_accessor這兩個方法,由於Class是Module的子類別,所以也可以使用這兩個attr_開頭的方法,那這兩個方法是在做什麼呢?

* attr_reader會替具有相同名稱的實體變數建立一般的getter方法
* attr_accessor會建立getter與setter方法
* (較不常用的attr_writer會建立setter方法)

例如上面年齡的方法我們可以改寫成:

class RubyGirl
  attr_accessor :age
end

是的就這樣,就一行,已經完成了剛剛上面的兩個getter與setter方法,age可以用symbol也可以用string的方式寫。此時,我們可以試著新增一個物件:

linda = RubyGirl.new
=> #<RubyGirl:0x007fcae211e928>

linda.age
=> nil

#因為沒有給初始值,所以出現nil,但是可以getter的!(如果不能getter會說沒有這個方法!)

linda.age=20
=> 20

#也成功改變了age的值,可以setter才可以做到這件事。

當然如果你不想被改變這個值的話,你可以用attr_reader:

class RubyGirl
  attr_reader :favorite
  attr_accessor :age
end

linda.favorite = "ruby"
NoMethodError: undefined method `favorite=' for #<RubyGirl:0x007fcae211e928 @age=20>

注意到了嗎?當你想要把linda物件的favorite方法改成"ruby"時,它不讓你改就是因為沒有favorite=這個方法,也就是沒有setter的方法!

好的,我們來做個統整吧!把昨天跟今天的程式碼整理成:

class RubyGirl
  attr_accessor :age
  def initialize(ruby_skill=0)
    @ruby_skill = ruby_skill
  end
end

ironman = RubyGirl.new(10)
=> #<RubyGirl:0x007fcae21472b0 @ruby_skill=10>

ironman.age
=> nil

ironman.age = 25
=> 25

總而言之,讀取和設定變數是分開的兩個方法,差別只在於有沒有等號,兩個方法都要使用的話,則可以簡寫成attr_accessor這個方法。

=================================================

19天,

“Replace fear of the unknown with curiosity.”

面對不知道的領域,一定要保持好奇心才行,對Ruby的好奇心從第一天到現在都還在,好險好險....


上一篇
Ruby女孩(18):自己的類別自己做啦!
下一篇
Ruby女孩(20):一次弄懂一件事,今天來分清楚實體方法跟類別方法的差異!
系列文
Ruby女孩:10萬.times { puts "為什麼?" }30

尚未有邦友留言

立即登入留言